Conditional display of parent posts in CRED

   Ana

October 29, 2013

Today we are going to see how to filter inputs in a CRED form. Our example will show filtering songs, so that the available options are all songs written by the current user.

This is what we’re going to do:

  • Create a CRED form
  • Create a View that lists all the posts that we want to show
  • Write a bit of Javascript, using jQuery, to limit the results in the form input

We start by creating and configuring our custom post types let’s use ‘Songs’ and ‘Musicians’. Songs will belong to musicians.

CRED form for new song
CRED form for new song

Now build a CRED form that will create songs. When creating a new song, users need to select what musician it belongs to. CRED can list all available parents, to choose from. We are going to limit this selection to only ‘my musicians’. Meaning, the musicians that were created by the currently logged in WordPress user.

Let’s see how to accomplish this:

1. Create a view that will list all parent post that you want to display in the CRED form. It should select posts of type ‘Musicians’ with the author the same as the current logged in user. Let’s name it ‘my musicians listing’. To clarify, this is an auxiliary View. The output will appear in the page, but will not be visible. We will use this output in our Javascrip for the filtering logic.

2. We are going to wrap the view HTML output with a div with id=”aux_musicians_list”. We’ll show the ID of the post enclosed in this class ‘aux_id’.

<div id="aux_musicians_list" style="display:none">
  <wpv-loop>
    <div class="aux_id">{{wpv-post-id}}</div>
  </wpv-loop>
</div>

Because we want to hide the view HTML output we have added style=”display:none” to the enclosing div.

insert this view in your CRED form

{{wpv-view name="my musicians listing"}}

the HTML output of the view when inserted in the CRED form will be:

<div id="aux_musicians_list" style="display:none">
    <div class="aux_id">292</div>
    <div class="aux_id">290</div>
</div>

here we have a list of ID’s of ‘Musicians’ for whom the author is the current logged in user.

Unfiltered list of musicians
Unfiltered list of musicians

make sure you have added the field for listing parent post in your CRED form. The select field will display the following HTML output:

<select name="_wpcf_belongs_musicians_id" id="cred_form_15_1__wpcf_belongs_musicians_id" class="myzebra-control myzebra-select myzebra-prime-name-_wpcf_belongs_musicians_id">
    <option value="-1">-- choose a musician --</option>
    <option value="292">Musician #6</option>
    <option value="290">Musician #5</option>
    <option value="14">Musician #4</option>
    <option value="13">Musician #3</option>
    <option value="12">Musician #2</option>
    <option value="9">Musician #1</option>
</select>

So we have a list of all available post type musicians. If we look at this HTML markup we see that the ID of the post is being passed to each option of the select by the value attribute. So we can relate the Views information and the select field together using the ID of the post. How to do this?

for this we are going to use some jQuery.
first we identify the select we want in this case the one with the ‘_wpcf_belongs_musicians_id’ in the name attribute

var select = $('select{{name="_wpcf_belongs_musicians_id"}}');

then we look for the div that will contain our options of ‘Musicians’ this one will have ‘aux_musicians_list’ in the id attribute.

var list = $('#aux_musicians_list') || $('<div id="aux_musicians_list"></div>');

With this we are defining our select and the div that will have our options list, in this case we are also assuring that a list exists whether it came from our view or we provide an empty one.

if our select has values and has any selected we get that value.

var selected = select.val();

Clone the select list and delete all the options. Why do a clone? Well to ensure that we have the same ids and the events that the original select has.

var new_select = select.clone(true, true);
new_select.children().remove();

Then loop through our options list (provided by the view output) and attach each corresponding option from the original select to the cloned select.

$('.aux_id', list).each(function(index, element) {
var id = $(element).text() || 0;
$('option{{value="' + id + '"}}', select).appendTo(new_select);
});

Finally set the original selected option and replace the original select with our own filtered clone select.

new_select.val(selected);
select.replaceWith(new_select);

the full custom code that we add to the custom JS for the CRED form is:

jQuery(document).ready(function($) {
    try {
        var select = $('select{{name="_wpcf_belongs_musician_id"}}');
        var list = $('#aux_musicians_list') || $('div id="aux_musicians_list"></div>');
        if (select.length) {
            var selected = select.val();
            var new_select = select.clone(true, true);
            new_select.children().remove();
            $('.aux_id', list).each(function(index, element) {
                var id = $(element).text() || 0;
                $('option{{value="' + id + '"}}', select).appendTo(new_select);
            });
            new_select.val(selected);
            select.replaceWith(new_select);
        }
    } catch(e) {
    }
});

Remember to change the name of the field according to your parent field name in our case is musicians ‘_wpcf_belongs_musician_id’.

The final HTML output for the select field looks like this:

<select name="_wpcf_belongs_musicians_id" id="cred_form_15_1__wpcf_belongs_musicians_id" class="myzebra-control myzebra-select myzebra-prime-name-_wpcf_belongs_musicians_id">
    <option value="292">Musician #6</option>
    <option value="290">Musician #5</option>
</select>

Correctly filtered list of musicians
Correctly filtered list of musicians

See how we’ve filtered the select options, so that they only include the ‘musicians’ created by the logged in user.

 

Comments 18 Responses

  1. I really appreciate these little tutorials, especially because they demonstrate how to add that little bit extra custom functionality to Toolset which is often all that’s required to finish more complex websites.

    Please keep them coming!!

  2. Hi Ana

    I would really like to get this working but something is not quite right.

    I set up my CRED form and then View.

    My view creates the subset of codes in the sequence that I want. Note that I adjusted the code you provided by changing the to

    ==========================

    [wpv-post-id]

    ==========================

    I added the View to the top of the CRED form

    ==========================
    [credform class=”cred-form”]
    [wpv-view name="Events List Future Only"]
    [cred-field field=”form_messages” value=””]
    ==========================

    I then added the code to the CRED JS box.

    ==========================
    jQuery(document).ready(function(e) {
    try {
    var select = $(‘select[name=”_wpcf_belongs_event_id”]’);
    var list = $(‘#aux_events_list) || $(‘div id=”aux_events_list”>’);
    if (select.length) {
    var selected = select.val();
    var new_select = select.clone(true, true);
    new_select.children().remove();
    $(‘.aux_id’, list).each(function(index, element) {
    var id = $(element).text() || 0;
    $(‘option[value=”‘ + id + ‘”]’, select).appendTo(new_select);
    });
    new_select.val(selected);
    select.replaceWith(new_select);
    }
    } catch(e) {
    }
    });
    ==========================

    The result is that the dropdown is unchanged and includes all parent events.

    I have set up a test page so you can see my form.
    http://www.505news.co.uk/test-page/

    Regards
    Tony
    If I can get this working it will solve some real problems we have with ever increasing drop downs!

    • Hi Tony,

      please update your javascript function with this one:

      jQuery(document).ready(function($) {
      try {
      var select = $(‘select[name="_wpcf_belongs_event_id"]‘);
      var list = $(‘#aux_events_list’) || $(‘div id=??aux_events_list??></div>’);
      if (select.length) {
      var selected = select.val();
      var new_select = select.clone(true, true);
      new_select.children().remove();
      $(‘.aux_id’, list).each(function(index, element) {
      var id = $(element).text() || 0;
      $(‘option[value="' + id + '"]‘, select).appendTo(new_select);
      });
      new_select.val(selected);
      select.replaceWith(new_select);
      }
      } catch(e) {
      }
      });
      

      it seams we were missing a single quote after $(‘#aux_events_list’).
      Also you can replace the e variable with a $ variable as the function parameter, in your case your site is using jQuery.noConflict().

  3. jQuery(document).ready(function(e) {
    try {
    var select = $(‘select[name=”_wpcf_belongs_event_id”]’);
    var list = $(‘#aux_events_list) || $(‘div id=”aux_events_list”>’);
    if (select.length) {
    var selected = select.val();
    var new_select = select.clone(true, true);
    new_select.children().remove();
    $(‘.aux_id’, list).each(function(index, element) {
    var id = $(element).text() || 0;
    $(‘option[value=”‘ + id + ‘”]’, select).appendTo(new_select);
    });
    new_select.val(selected);
    select.replaceWith(new_select);
    }
    } catch(e) {
    }
    });

    It seemes that
    /div>’);

    was chopped from the end of line 4

    • Hi Ana

      I managed to get rid of the red highlighted code by over-typing the single quotes but it’s still not working.

      Any suggestions appreciated.

      My code is now:


      jQuery(document).ready(function($) {
      try {
      var select = $(‘select[name="_wpcf_belongs_event_id"]‘);
      var list = $('#aux_events_list') || $('div id=??aux_events_list??>');
      if (select.length) {
      var selected = select.val();
      var new_select = select.clone(true, true);
      new_select.children().remove();
      $(‘.aux_id’, list).each(function(index, element) {
      var id = $(element).text() || 0;
      $(‘option[value="' + id + '"]‘, select).appendTo(new_select);
      });
      new_select.val(selected);
      select.replaceWith(new_select);
      }
      } catch($) {
      }
      });

      • Hi Tony,

        the example described in the blog post assumes we are configuring the CRED form with Basic theme CSS styling.
        From what I’ve seen in your example your using the Styled theme, that will make the code a bit more complicated.
        I’ve sent you an example of how to do this in a general manner for both styling options.

        • Hi Ana

          Yes this all works fine – I had not thought about the form styling affecting the code.

          Thank you for your efforts – you and the team always seem to come up with solutions for us less abled developers!

          Tony

  4. Hello Ana,

    I am trying to use this on my web site but it does not work. I have created the View (slug=menu-manuscripts-under-review) with:

    [wpv-post-id]

    I have introduced the view in CRED in the 2nd line:
    [credform class=”cred-form cred-keep-original”]
    [wpv-view name="menu-manuscripts-under-review"]
    and in the JavaScript box:
    jQuery(document).ready(function($) {
    try {
    var select = $(‘select[name=”_wpcf_belongs_article_id”]’);
    var list = $(‘#aux_manuscripts_under_review_list’) || $(‘div id=”aux_manuscripts_under_review_list”>’);
    if (select.length) {
    var selected = select.val();
    var new_select = select.clone(true, true);
    new_select.children().remove();
    $(‘.aux_id’, list).each(function(index, element) {
    var id = $(element).text() || 0;
    $(‘option[value=”‘ + id + ‘”]’, select).appendTo(new_select);
    });
    new_select.val(selected);
    select.replaceWith(new_select);
    }
    } catch(e) {
    }
    });

    Now, looking at the output html code of the page, I see the correct selection list:

    2561

    2577

    But then, the html output code for the select menu is unchanged:

    — Select Title —
    Nullam accumsan lorem in dui
    Aenean commodo ligula eget dolor
    Etiam rhoncus

    And the html page actually does not show the select menu correctly at all, it is shrinked and blank (empty). It seems that the script blocks, but I don’t have enough knowledge of JQuery to find where and why.

    Your help would be very much appreciated.

    Thanks in advance,
    Michel

    • Hi Michel,

      just to confirm a few steps:
      1. in the auxiliary view that you’ve created your using a div with id=”aux_manuscripts_under_review_list” this is the id we will be looking for to retrieve the id’s
      2. the parent slug is ‘article’

      Thanks,
      Ana

        • Hi Michel,

          we are missing a class=”aux_id” associated to the div that will list the ID’s in the auxiliary view.
          So the HTML inside the loop would be something like this
          div class=”aux_id” [wpv-post-id] /div

          This class will be used in the javascript code to retrieve the information.

  5. Hello Ana,
    I’m trying to use your solution.
    I have 2 type “Enfant” and “Planning” which are parent of “Inscription”. I have a Cred form belonging to “Inscription Atelier” where I want to link one Enfant to one Planning. What I want is to have the list of Enfant belonging to the current logged user.
    I tried several ways to manage this and until now, didn’t succeed.

    Here’s the code in my Cred :

    [credform class=”cred-form cred-keep-original”]

    [cred_field field=”form_messages” value=””]

    Inscription à un atelier

    Choisir l’atelier concerné :
    [cred_field field=”_wpcf_belongs_plannings_id” value=”” order=”title” ordering=”asc” no_parent_text=”Choisissez l’atelier”]

    Choisir l’enfant concerné :
    [cred_field field=”_wpcf_belongs_enfants_id” value=”” order=”title” ordering=”asc” no_parent_text=”Choisissez l’enfant”]

    [cred_field field=”form_submit” value=”Envoyer” urlparam=””]
    [/credform]

    And added your Jquery :
    jQuery(document).ready(function($) {
    try {
    var select = $(‘select[name=”_wpcf_belongs_enfants_id”]’);
    var list = $(‘#aux_musicians_list’) || $(‘div id=”aux_enfants_list”>’);
    if (select.length) {
    var selected = select.val();
    var new_select = select.clone(true, true);
    new_select.children().remove();
    $(‘.aux_id’, list).each(function(index, element) {
    var id = $(element).text() || 0;
    $(‘option[value=”‘ + id + ‘”]’, select).appendTo(new_select);
    });
    new_select.val(selected);
    select.replaceWith(new_select);
    }
    } catch(e) {
    }
    });

    Can you see what’s missing here ?
    Many thnaks
    Pat

    • Just a comment : “Enfant?? and “Planning?? which are parent of “Inscription Atelier??.
      Sorry for this.
      Pat

      • Hi Pat,

        from the code you have pasted here I think you need to update the following variable:


        var list = $(‘#aux_musicians_list’) || $(‘div id=??aux_enfants_list??>’);

        as your using the id from the example aux_musicians_list, so it would probably be like this:

        var list = $(‘#aux_enfants_list’) || $(‘div id=??aux_enfants_list??>’);

        note that this is the ID of the auxiliary div added using Views to filter the content of the parents select field.

        if you need further assistance customising this example, please open a ticket in our support forum. I’ll help you there 🙂

        Thanks

  6. This is great, thank you! But how do you go about using this multiple times on the same page, with the same CRED parent? I have different cred forms that have the same parent options. The javascript gets confused now that there are multiple “selects” with the same ID’s and multiple “Aux…” lists.
    Thanks