DxJR Posted December 8, 2017 Share Posted December 8, 2017 So, I've tried looking through here and Can't seem to find it. I'm trying to create a situation in the admin where: I have a page reference InputField. When the user chooses one of those pages, from the dropdown, a new Page reference drop down pops up with that pages children in it. I know how to do the "show only if..." thing, but How did I make it dynamically pull in a pages children? Thanks Link to comment Share on other sites More sharing options...
Jonathan Lahijani Posted December 8, 2017 Share Posted December 8, 2017 There's a commercial module for that: 1 Link to comment Share on other sites More sharing options...
adrian Posted December 8, 2017 Share Posted December 8, 2017 Depending on how complex your needs are, the core does offer some support. Use something like this for the selector value for a page field: parent=page.otherpagefield That allows for ajax population of one select based on the selected value of the otherpagefield 4 Link to comment Share on other sites More sharing options...
Karl_T Posted December 9, 2017 Share Posted December 9, 2017 7 hours ago, adrian said: Depending on how complex your needs are, the core does offer some support. Use something like this for the selector value for a page field: parent=page.otherpagefield That allows for ajax population of one select based on the selected value of the otherpagefield Is it possible to apply to fields within repeater? It is working great without using repeater, but it is not when the fields are inside a repeater item even after saving the page. Link to comment Share on other sites More sharing options...
Macrura Posted December 9, 2017 Share Posted December 9, 2017 I needed the same thing so i used Selectize inputfield single for the master select and then a select multiple on the dependent select, then i initialized the 2nd one using Selectize JS; the JS is not so hard, but you do need to have a custom select multiple that has a data-parent attribute on each option; those are filtered to match the selected option in the 'parent' select. Eventually this will make it into InputfieldSelectize somehow, but for now it's just done by adding JS, courtesy of AdminCustomFiles.. In the screen capture, you will see the left select, which may or may not have child pages; if it does, then the right one shows the children: Spoiler var initChildSelect = function() { // THE "PARENT" FIELD var thisID = $(this).attr('id'); var repeaterID = thisID.split('_repeater')[1]; // if in repeater? var optID = parseInt($(this).val()); // the selected option // THE "CHILD/DEPENDENT" FIELD childWorksSelect = $('select[name^="part_select_repeater'+repeaterID+'"]'); var allOptions = $(childWorksSelect.children()).clone(); var validOptions = allOptions.filter(function(){ return $(this).data('parent') == optID; }); childWorksSelect.html(validOptions); var options = {}; if(!optID) { var options = {'placeholder': 'No Work Selected'} } if(optID && !validOptions.length) { var options = {'placeholder': 'No Parts For The Selected Work'} } childWorksSelect.selectize(options); // DEAL WITH CHANGES TO THE PARENT FIELD $(this).change(function() { var optID = parseInt($(this).val()); var newOptions = allOptions.filter(function(){ return $(this).data('parent') == optID; }); childWorksSelect[0].selectize.destroy(); // Re-init the select childWorksSelect = $('select[name^="part_select_repeater'+repeaterID+'"]'); childWorksSelect.html(newOptions); var options = {}; if(!optID) { var options = {'placeholder': 'No Work Selected'} } if(optID && !newOptions.length) { var options = {'placeholder': 'No Parts For The Selected Work'} } childWorksSelect.selectize(options); childWorksSelect[0].selectize.open(); }); } $(function(){ $('select[name^="work_select_single"]').each(initChildSelect); $(document).on('reloaded opened repeateradd wiretabclick', '.InputfieldPage', function() { $(this).find('select[name^="work_select_single"]').each(initChildSelect); }); }); 9 Link to comment Share on other sites More sharing options...
Karl_T Posted December 9, 2017 Share Posted December 9, 2017 Thanks for your solution @Macrura. I found that the reason why dynamic function is not working. This is because the class of the select field are amended by the repeater so the jquery is not able to select the DOM correctly. What we should do is to fix it by targeting the correct DOM by changing the selector. I can get it to work with already saved repeater page but not the newly added one. I think a listener is needed to attach the on change event to newly added repeater item when we press Add New. EDIT: The newly added repeater item surprisingly fires the js again. It is working fine now. A small bug is that the old repeater items will fire more than once if there are more than one newly added item. Below is the amended JS file for InputfieldPage in quick Spoiler function initInputfieldPage($this) { $this.find("p.InputfieldPageAddButton a").click(function() { var $input = $(this).parent('p').next('.InputfieldPageAddItems'); if($input.is(":visible")) $input.slideUp('fast').find(":input").val(''); else $input.slideDown('fast').parents('.ui-widget-content').slice(0,1).effect('highlight', {}, 500) return false; }); // support for dependent selects $this.find(".findPagesSelector").each(function() { var $repeater = $this.parents('.InputfieldRepeaterItem'); var $t = $(this); var selector = $t.val(); // if there is no "=page." present in the selector, then this can't be a dependent select if(selector.indexOf('=page.') == -1) return; var labelFieldName = $t.attr('data-label'); var formatName = $t.attr('data-formatname'); if(!labelFieldName.length) $labelFieldName = 'name'; // if it doesn't contain a dynamic request from the page, then stop now var $wrap = $t.parents(".InputfieldPage"); var $select = $('select#' + $wrap.attr('id').replace(/^wrap_/, '')); if($select.length < 1) return; var parts = selector.match(/(=page.[_a-zA-Z0-9]+)/g); for(var n = 0; n < parts.length; n++) { var part = parts[n]; var name = part.replace('=page.', ''); var $inputfield = $repeater.length === 0 ? $('#Inputfield_' + name) : $('#Inputfield_' + name + "_repeater" + $repeater.data('page')); if($inputfield.length < 1) return; // monitor changes to the dependency field $inputfield.off('change'); $inputfield.on('change', function() { var s = selector; var v = $inputfield.val(); if(v == null) { // no values selected $select.children().remove(); $select.change(); return; } v = v.toString(); v = v.replace(/,/g, '|'); // if multi-value field, convert commas to pipes s = s.replace(part, '=' + v); s = s.replace(/,\s*/g, '&'); if(s.indexOf('_LPID')) s = s.replace(/_LPID[0-9]+/g, ''); var url = ProcessWire.config.urls.admin + 'page/search/for?' + s + '&limit=999&get=' + labelFieldName; if(formatName.length) url += '&format_name=' + formatName; $.getJSON(url, {}, function(data) { //$select.children().remove(); $select.children().addClass('option-tbd'); // mark existing options as to-be-deleted for(n = 0; n < data.matches.length; n++) { var page = data.matches[n]; // first see if we can find the existing option already present var $option = $select.children("[value=" + page.id + "]"); // if that option isn't already there, then make a new one var selected = false; if($option.size() > 0) selected = $option.is(":checked"); $option.remove(); var label = ''; if(formatName.length) label = page[formatName]; if(!label.length) label = page[labelFieldName]; if(!label.length) label = page.name; var $option = $("<option value='" + page.id + "'>" + label + "</option>"); if(selected) $option.attr('selected', 'selected'); // add the <option> to the <select> $select.append($option); } $blankOption = $("<option value=''></option>"); $select.prepend($blankOption); $select.children(".option-tbd").remove(); $select.change(); }); }); } }); } $(document).ready(function() { $(".InputfieldPage").each(function() { initInputfieldPage($(this)); }); $(document).on("reloaded", ".InputfieldPage", function() { initInputfieldPage($(this)); }); }); EDIT: The bug is fixed. I have submited a pull request. Hope we could see this feature in the core soon! 4 Link to comment Share on other sites More sharing options...
Macrura Posted December 9, 2017 Share Posted December 9, 2017 would be awesome if core natively supported dependent selects in repeaters! 6 Link to comment Share on other sites More sharing options...
Fuzen Posted April 15, 2022 Share Posted April 15, 2022 On 12/8/2017 at 10:23 PM, Karl_T said: Is it possible to apply to fields within repeater? It is working great without using repeater, but it is not when the fields are inside a repeater item even after saving the page. As of today, yes! On 12/9/2017 at 8:36 AM, Macrura said: would be awesome if core natively supported dependent selects in repeaters! Your prayers were answered today ? 1 Link to comment Share on other sites More sharing options...
sz-ligatur Posted March 7 Share Posted March 7 On 12/8/2017 at 9:10 PM, adrian said: Depending on how complex your needs are, the core does offer some support. Use something like this for the selector value for a page field: parent=page.otherpagefield That allows for ajax population of one select based on the selected value of the otherpagefield Hello @adrian & @Fuzen – I have tried this without success. May I ask you what it needs to set up? I need a second select (field b), that offers options related to the selected value in field a. Pages structure: _dir-tpls/ > Template 1 [chunk-tpl]/ >> Option 1 [tpl-option] >> Option 2 [tpl-option] >> … > Template 2 [chunk-tpl] >> Option … On a settings page I have these two fields: field a: name: select_tpl, type: select-option-single config > parent => _dir-tpls/ config > template => chunk-tpl field b: name: tpl_options, type: checkbox-multi config > parent => '' config > template => tpl-option config > findPagesSelector => 'parent=page.select_tpl' //include=hidden It doesn't show any options in the select field b. If I leave the findPagesSelector empty, all option pages [tpl-option] are listet. You say it's a core feature, so I guess it should work without any additional JS? Or did I get you wrong? I would be happy if you could help me with a hint – thank you! Link to comment Share on other sites More sharing options...
Robin S Posted March 7 Share Posted March 7 @sz-ligatur, the dependent selects feature only works if both inputfields are one of the following: Select, Select Multiple or AsmSelect @ryan, it would be great to have this feature documented somewhere. 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now