mrackley / StratusForms

Lightweight InfoPath alternative for SharePoint 2007,2010,2013,2016,2019 and Office 365
82 stars 36 forks source link

Checkboxes & Radio Stay Checked #37

Open drewtothegame opened 5 years ago

drewtothegame commented 5 years ago

I'm having good success with implementing StratusForms aside from anything related to radio or checkbox inputs. It seems no matter how I manage these, StratusForms will not release the 'checked' status of the HTML inputs. I've noticed that the JSON is all kinds of messed up with these inputs, which is fine, since I'm promoting to an SP field. New items work fine but any type of edit against an existing item is setting the inputs to 'checked' if at anytime in the past they've been submitted as a value. Attempted a bunch of tricks trying to get this resolved but I think i'm fighting a losing battle and will have to move onto another product unless someone has any tips?

I've browsed the other reports that are similar to this but since I'm using the published StratusForms web part and not the older CEWP version, I don't see a way to manipulate the base code. Am I missing something here?

davidcfk commented 5 years ago

I don't see any way of fixing anything except modifying the base code haha :) I'll give the checkbox issue a go, the issue identified at #11 relates to this, though I solved it for radio buttons only...

David

davidcfk commented 5 years ago

buildStratusFormsDataObject function in stratus-forms-1.5.js, is missing the following statement for when checkboxes were deselected... causing the data to be incorrect if the form has been toggled during a second submission. To cure that problem in the function, add the line towards the bottom of this code segment.

if ((type.toUpperCase() != "RADIO" && type.toUpperCase() != "CHECKBOX")) {
                        formDataObject[id] = encodedValue;
                    } else {
                            if ($(this).is(':checked')) {
                            if (type.toUpperCase() == "CHECKBOX") {
                                    value = "1";
                            }
                            formDataObject[id] = value;
                        } else {
                            if (type.toUpperCase() == "CHECKBOX") {
                                //if checkbox is not checked we need to clear the associated
                                //SharePoint list field if one is mapped
                                value = "0";
                            } else {
                                formVal = undefined;
                            }
                            formDataObject[id] = value; // add this line
                        }
                    }

The next comment will deal with fetching the values and re-applying it back to the form fields...

davidcfk commented 5 years ago

It's weird the code towards the end of Populate Form Data seems to assume the checkboxes were checked to begin with. With the problem of the StratusFormsData for checkboxes resolved (see previous comment, we can start working on fixing the form element to make sure it's displayed correctly - see below).

Towards the end of PopulateFormData function in stratus-forms-1.5.js, change two lines (see towards the bottom of the code segment)

else {
    var value = listFields[$(element).attr("ListFieldName")];
    if (value == undefined) {
        var regex = new RegExp("<br>", "g");
      value = formData[field].replace(regex, "\n");
        }
        if ($(element).attr("type") == "radio" || $(element).attr("type") == "checkbox") {
            // This section for the radio button fixes the radio button population issue when the correct value is already in sharepoint field
            if ($(element).attr("type") == "radio" && $(element)[0].value == value) { 
                $(element).attr("checked", "checked");
            }
            if ($(element).attr("type") == "checkbox" && value == 1) {  // change this!
                $(element).attr("checked", "yes"); // and change this!
      }
    }
    else {
        $(element).val(htmlDecode(value, element));
    }
}
davidcfk commented 5 years ago

Because it's loading the radio button options correctly with the code above, I may as well spend a few more minutes looking at what to change to correct the radio button saving behaviour in StratusFormsData (I believe simply omitting the unchecked element should be sufficient)... (you may want to check out my fork for these changes a little later...

davidcfk commented 5 years ago

https://github.com/davidcfk/StratusForms/commit/4c7a1c91925a3b53a301dd29f63a6b196440e566

drewtothegame commented 5 years ago

Thanks for taking a look at this David! Since I'm using the packaged webpart I went ahead and wrote some javascript to grab the radio inputs on change and dump them into a hidden text box. I post that text to the promoted SP field. The radio buttons themselves are grouped by name and do not have a listFieldName. I havent tackled the checkboxes yet as they seem a bit more finicky due the 'checked' state. If I cant get them working, I'll likely just setup my multi-values as 'yes/no' radio buttons. Here is the code in case anyone else would like to implement...

`


    <input type="text" class="promoted" id="locationChoice" listFieldName="Location" /><br/>

`

$("#SFForm").StratusFormsInitialize({ htmlForm: "https://connect.cityutil.com/sites/transit/SiteAssets/Supervisor%20Daily%20Status/minimal.html", queryStringVar: "formID", listName: "Supervisor Daily Status", completefunc: function() { $('input[class="promoted"]').each(function() { SetChoices(this.id, this.text) }) } }) }

$(document).on('change', 'input:radio', function() { //This is our click handler for ALL radio inputs. We're scanning for changes and grabbing the name value to pass into ChoicesReview() ChoicesReview(this.name) })

function ChoicesReview(radioGroupName) { //Grab all radios with checked state and append their values to single string instance var radios = document.querySelectorAll('input[name="' +radioGroupName+ '"]:checked'); var vals = ""; for (var i=0, n=radios.length;i<n;i++) { if (radios[i].checked) { vals += ","+radios[i].value; } } if (vals) vals = vals.substring(1); $('input[id="' +radioGroupName+ '"]').val(vals) }

function SetChoices(radioGroupName, radioGroupValue) { $('input[value="' +radioGroupValue+ '"][name="' +radioGroupName+ '"]').prop("checked", true) }

UPDATE #2 --> figured out a way to kind of reverse-engineer my above logic using the class=SFDontSave feature on the radio inputs. I've updated the code above which seems to be working for now.

davidcfk commented 5 years ago

Try mine :) it functions without needing to introduce hidden fields :)

On Sat., 17 Nov. 2018, 5:28 am drewtothegame <notifications@github.com wrote:

Well...I thought I had this working but it appears the checked status is persisting through my radio buttons as well. Probably going to have punt on StratusForms as a solution. Not developed enough for production.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mrackley/StratusForms/issues/37#issuecomment-439500880, or mute the thread https://github.com/notifications/unsubscribe-auth/AE22IymsCjkN7Ym1DBzwIU_p3sQc14-Lks5uvxHVgaJpZM4Yed_e .

plbowers commented 4 years ago

As far as I can see this problem is still unresolved in 1.55.

Here's how I fixed it (similar to @davidcfk 's fix above which I unfortunately found late), once again in PopulateFormData at the end:

            else {
        var value = listFields[$(element).attr("ListFieldName")];
                if (value == undefined)
                {
                    var regex = new RegExp("<br>", "g");
                    value = formData[field].replace(regex, "\n");               
                }

                if ($(element).attr("type") == "radio" || $(element).attr("type") == "checkbox") {
                    $(element).attr("checked", "checked");
            // PLB added this block modified from 1.55 
            if ($(element).is(':checkbox')) {
            if (value == 1) {
                $(element).prop('checked', true);
            } else {
                $(element).prop('checked', false);
            }
            }
                } else {
                    $(element).val(htmlDecode(value, element));
                }
            }

That (above) is working for me (at least as far as I've tested it). The problem with the code as it stands in 1.55 is that this part of the code:

          if ($(element).attr("type") == "radio" || $(element).attr("type") == "checkbox") {
              $(element).attr("checked", "checked");
          }

Appears after any attempt to set prop('checked') (and note that prop('checked') is never turned off) and if attr('checked') is set to 'checked' then it automatically turns on the prop('checked'). So the code says, in sum, "if element is a radio button or a checkbox then set it to checked" which is exactly what is happening in my code... By checking whether value==1 after this it allows prop('checked') to be turned on/off depending on the contents of value.

plbowers commented 4 years ago

Just in passing I will mention that this code:

$(element).prop('checked', false);
$(element).attr('checked','checked');
console.log($(element).prop('checked'));

seems to log "false" in certain circumstances. But I've confirmed pretty conclusively that

$(element).attr('checked','checked');

does, in fact, turn prop('checked') ON as long as that attr('checked') was undefined previous. If you find results that seem to contradict this, please let me know and I'll come up with a pastebin that demos it - as I said, it wasn't immediately apparent what was going on based on the results of console.log() interspersed in this code...

sandve13 commented 3 years ago

Thanks David and plbowers! Hopefully that will be included if there's a new release.

qaudaffyazmi commented 3 years ago

I have the same issue. Currently use web part provided to load the form, so I guess all those required file is preloaded by the web part right? Just wonder how the web part load the base js code? is it deployed somewhere in our SharePoint server or load from cdn/cloud? If it is loaded from cdn/cloud, how can I edit the base code to solve the issue?

paparush commented 3 years ago

@qaudaffyazmi this is exactly where I am too. Using the SP Fx web part and unable to edit the underlying Stratus.js like I could do when we were running on Prem.