Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 9 of 9
  1. #1
    New to the CF scene
    Join Date
    Jun 2012
    Posts
    5
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Multi-Select Picklist Not Saving

    I copied some code to create a multi-select picklist out of an option set in Dynamics CRM. Basically, I have a drop-down list and this script turns into an element with multiple checkbox options. When the form loads, the checkboxes form. When the user saves the form, it stores the selected choices in a text box that's hidden from the user.

    The problem I'm having is that when a user only selects one option and saves, upon re-loading the form the checkboxes are blank (the one option that was selected is blank). Also, when they select all options and save, one option is unechecked upon reloading. Is there a way so that if they save with one option or all options checked, that the form reloads showing the appropriate selections?

    Code:
    function OpportunityOnLoad ()
    {
    // PL - the picklist attribute; PLV - used to save selected picklist values     
    var PL = crmForm.all.new_reasons;     //CREATE NEW PICKLIST
    var PLV = crmForm.all.new_reasonstext;  //CREATE NEW TEXT FIELD TO STORE STRING
     
    
    PL.style.display = "none";       //HIDES THE CONTROL
    PLV.style.display = "none";     //HIDES THE CONTROL
    
     
        // Create a DIV container    
        var addDiv = document.createElement("<div style='overflow-y:auto; height:135px; width:278px; border:1px #a1a5aa solid; background-color:#ffffff;' />");    
        PL.parentNode.appendChild(addDiv);    
        // Initialise checkbox controls    
     
    
        for( var i = 1; i < PL.options.length; i++ )    
        {    
            var pOption = PL.options[i];    
            if( !IsChecked( pOption.text ) )   
            var addInput = document.createElement("<input type='checkbox' onclick='CallOnChangeEvent()' style='border:none; width:25px; align:left;' />" );
            else    
            var addInput = document.createElement("<input type='checkbox' onclick='CallOnChangeEvent1()' checked='checked' style='border:none; width:25px; align:left;' />" );
            var addLabel = document.createElement( "<label />");    
            addLabel.innerText = pOption.text;    
    
    
            var addBr = document.createElement( "<br>"); //it's a 'br' flag    
    
    
            PL.nextSibling.appendChild(addInput);    
            PL.nextSibling.appendChild(addLabel);    
            PL.nextSibling.appendChild(addBr);
        }
     
    
       // Check if it is selected    
       function IsChecked( pText )
       {
       if(PLV.value != "")
          {
          var PLVT = PLV.value.split(", ");
          for( var i = 0; i < PLVT.length; i++ )
          {
             if( PLVT[i] == pText )
             return true;
          }
        }
        return false;
       }
    }
     
    
    function CallOnChangeEvent()
    {
          var PL = crmForm.all.new_reasons;  
          var PLV = crmForm.all.new_reasonstext;
          PLV.value = "";
          var getInput = PL.nextSibling.getElementsByTagName("input");
          for( var i = 0; i < getInput.length; i++ )
          {
             if( getInput[i].checked)
             {
                PLV.value += getInput[i].nextSibling.innerText + ", ";
             }
          }
     
    
         //MUST DO THIS TO TRIGGER A SAVE EVENT
         var Name = Xrm.Page.data.entity.attributes.get("new_reasonstext");
        Name.setValue(PLV.value);
    }

  • #2
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,536
    Thanks
    80
    Thanked 4,490 Times in 4,454 Posts
    Don't know how we could guess what the problem is without seeing how the selected check boxes are saved and how the <select> is then created upon re-load.

    And you don't even show the code for the IsChecked function.

    In any case, this seems to me like a silly way to do this. Why not change the server-side code to create the checkboxes directly, instead of the <select>???
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #3
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,536
    Thanks
    80
    Thanked 4,490 Times in 4,454 Posts
    And the other part of the code that is silly, to me, is that you call the CallOnChangeEvent function on each checkbox change. Why not just call it once, when the <form> is submitted?
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #4
    New to the CF scene
    Join Date
    Jun 2012
    Posts
    5
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by Old Pedant View Post
    Don't know how we could guess what the problem is without seeing how the selected check boxes are saved and how the <select> is then created upon re-load.

    And you don't even show the code for the IsChecked function.

    In any case, this seems to me like a silly way to do this. Why not change the server-side code to create the checkboxes directly, instead of the <select>???
    I should've mentioned it's the online version of MS Dynamics CRM, so I can't access server code. The IsChecked is on there.

  • #5
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,536
    Thanks
    80
    Thanked 4,490 Times in 4,454 Posts
    Okay, but we would still need to see what the <select> that is produced looks like.

    Oh...and I would think that the better way to do this would be to HIDE the <select> and then, when the <form> is submitted, you simply go back to the <select> and add SELECTED to the <option>s that correspond to the checked checkboxes!

    And this code makes no sense, given the comment attached to it:
    Code:
    var PLV = crmForm.all.new_reasonstext;  //CREATE NEW TEXT FIELD TO STORE STRING
    That doesn't "CREATE" one darned thing. Unless that field already exists, your PLV variable is simply going to be NULL, so of course nothing after that works.

    And, not so incidentally, this code will ONLY work in MSIE. "all" is only supported by MSIE. (Well, and some versions of Opera, I have heard.)
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #6
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,536
    Thanks
    80
    Thanked 4,490 Times in 4,454 Posts
    The more I look at that code, the dumber it looks. What a ridiculous way to find out if a given <option> is selected!

    Try this much simpler code. That, not so incidentally, works in FF and Chrome, which your code wouldn't come close to doing.
    Code:
    <html>
    <body>
    <form name="crmForm">
    <div>
       <select name="new_reasons" multiple size="7">
       <option>choose one or more</option>
       <option>Bad Breath</option>
       <option selected>Body Odor</option>
       <option selected>Too Dumb</option>
       <option>Too Smart</option>
       </select>
    </div>
    <hr/>
       <input type="submit"/>
    </form>
    
    <script type="text/javascript">
    function OpportunityOnLoad ()
    {
         // I assume you have a form named "crmForm"
         var form = document.crmForm;
    
         // *OR* if the <form> has an ID of "crmForm" instead, use:
         // var form = document.getElementById("crmForm");
    
         // and I assume you have a <select name="new_reasons" multiple>
         var PL = form.new_reasons;    
    
    
        // to see this work, do *NOT* hide the <select>
        // so UN-comment next line after you are satisified that it works
        // PL.style.display = "none"; // hide the <select>
    
     
        // Create a DIV container    
        var addDiv = document.createElement("div");
        addDiv.style.overflowY = "auto";
        addDiv.style.height = "135px";
        addDiv.style.width = "278px";
        addDiv.border = "solid 1px #a1a5aa"
        addDiv.backgroundColor = "white";
    
        PL.parentNode.appendChild(addDiv);    
    
        // Initialise checkbox controls    
        for( var i = 1; i < PL.options.length; i++ )    
        {    
            var pOption = PL.options[i];
            var cb = document.createElement("input");
            cb.type = "checkbox";
            cb.style.border = "none";
            cb.width = "25px";
            cb.align = "left";
            cb.id = "ZZZCB_" + i;
            cb.checked = pOption.selected;
            cb.onclick = function() {
                var sel = this.form.new_reasons;
                var optnum = Number(this.id.replace("ZZZCB_",""));
                sel.options[optnum].selected = this.checked;
            }
            var addLabel = document.createElement( "label");    
            addLabel.for = "ZZZCB_" + i;
            addLabel.innerHTML = pOption.text;    
    
            var addBr = document.createElement("br"); 
            addDiv.appendChild(cb);    
            addDiv.appendChild(addLabel);    
            addDiv.appendChild(addBr);
        }
    
     
    }
    OpportunityOnLoad();
    </script>
    </body>
    </html>
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #7
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,536
    Thanks
    80
    Thanked 4,490 Times in 4,454 Posts
    Hmmm...I don't see why, but putting in the
    Code:
    addLabel.for = "ZZZCB_" + i;
    didn't cause the <label>s to act as true labels for the checkboxes.

    Okay, so let's hack it: Add an onclick method to the labels as well.
    Code:
            var addLabel = document.createElement( "label");    
            addLabel.for = "ZZZCB_" + i;
            addLabel.innerHTML = pOption.text;  
            addLabel.onclick = function() {
                document.getElementById(this.for).click();
            }
    
    Now the labels work as you would want them to.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #8
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,536
    Thanks
    80
    Thanked 4,490 Times in 4,454 Posts
    *** SIGH ***

    It figures. Now there is code in there that make MSIE barf! Even MSIE 9, which is *supposed* to be compatible!

    Okay...*NOW* this code works in MSIE 9, FF, and Chrome. You'll have to check it in MSIE 8 and below.

    Code:
    <html>
    <body>
    <form name="crmForm">
    <div>
       <select name="new_reasons" multiple size="7">
       <option>choose one or more</option>
       <option>Bad Breath</option>
       <option selected>Body Odor</option>
       <option selected>Too Dumb</option>
       <option>Too Smart</option>
       </select>
    </div>
    <hr/>
       <input type="submit"/>
    </form>
    
    <script type="text/javascript">
    function OpportunityOnLoad ()
    {
         // I assume you have a form named "crmForm"
         var form = document.crmForm;
    
         // *OR* if the <form> has an ID of "crmForm" instead, use:
         // var form = document.getElementById("crmForm");
    
         // and I assume you have a <select name="new_reasons" multiple>
         var PL = form.new_reasons;    
    
    
        // to see this work, do *NOT* hide the <select>
        // so UN-comment next line after you are satisified that it works
        // PL.style.display = "none"; // hide the <select>
    
     
        // Create a DIV container    
        var addDiv = document.createElement("div");
        addDiv.style.overflowY = "auto";
        addDiv.style.height = "135px";
        addDiv.style.width = "278px";
        addDiv.border = "solid 1px #a1a5aa"
        addDiv.backgroundColor = "white";
    
        PL.parentNode.appendChild(addDiv);    
    
        // Initialise checkbox controls    
        for( var i = 1; i < PL.options.length; i++ )    
        {    
            var pOption = PL.options[i];
            
            var cb;
            try {
                 // the idiotic MSIE way:
                 cb = document.createElement(
                         '<input type="checkbox" ' + ( pOption.selected ? "checked/>" : "/>")
                     );
            } catch( e ) {
                 // the right way:
                 cb = document.createElement("input");
                 cb.type = "checkbox";
                 cb.checked = pOption.selected;
            }
            cb.style.border = "none";
            cb.width = "25px";
            cb.align = "left";
            cb.id = "ZZZCB_" + i;
            cb.onclick = function() {
                var sel = this.form.new_reasons;
                var optnum = Number(this.id.replace("ZZZCB_",""));
                sel.options[optnum].selected = this.checked;
            }
            var addLabel = document.createElement( "label");    
            addLabel.id = "ZZZZCB_" + i; // notice the one extra "Z" (sneaky, no?)
            addLabel.innerHTML = pOption.text;  
            addLabel.onclick = function() {
                document.getElementById(this.id.substring(1)).click();
            }
    
            var addBr = document.createElement("br"); 
            addDiv.appendChild(cb);    
            addDiv.appendChild(addLabel);    
            addDiv.appendChild(addBr);
        }
    
     
    }
    OpportunityOnLoad();
    </script>
    </body>
    </html>
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #9
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,536
    Thanks
    80
    Thanked 4,490 Times in 4,454 Posts
    See, the best part about doing it this way is that the <select multiple> is still what is sent back to the server, so it can't even tell you have done anything!
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •