You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'd like to propose adding some hooks for JavaScript purposes when using Digestive Functors (not sure how much of this applies to non-Heist users). From a front-end perspective, the names of DF form fields have caused me a bit of trouble because I want to be able to write both my templates and my JavaScript to "just work" without having to hardcode things like form or subform names. Recently, I've been working on working with Digestive Aeson and would like to write an elegant solution that will go through the JSON response received from a submission made via XMLHttpRequest (AJAX) and match up the errors to the field they belong to. There's just one problem with that: Digestive Aeson doesn't tell you the form name.
Why this is a problem
Consider the following form:
dataFoo=Foo{name::Text
, age::Int
, account::Bar}dataBar=Bar{username::Text
, password::Text}fooForm::Monadm=>FormTextmFoo
fooForm =Foo<$>"name".: check "cannot be blank" (/="") (text Nothing)
<*>"age".: stringRead "not a number"Nothing<*>"account".: check "cannot have identical fields" (\ x -> username x /= password x) barForm
barForm::Monadm=>FormTextmBar
barForm =Bar<$>"name".: check "cannot be blank" (/="") (text Nothing)
<*>"password".: check "cannot be blank" (/="") (text Nothing)
Submitting with an empty JSON object returns the following information:
{"name":"cannot be blank","account":{"password":"cannot be blank","name":"cannot be blank"},"age":"not a number"}
The problem becomes: how do I match the results to the fields via JavaScript? If I select all of the fields and split the names on the period character, I can traverse the JSON results and find the error:
However, it becomes inefficient to deal with results like this where the subform, which has no corresponding field, returns an error:
{"name":"cannot be blank","account":"cannot have identical fields","age":"not a number"}
It would be more efficient to traverse the JSON result and check the DOM for fields that match (especially since it would be more common for the JSON object to be smaller than the collection of form fields). If they don't exist, then they get pushed into my global error pile.
functionunravelJSONObject(obj){varcollector=[];unraveler(obj,[]);functionunraveler(obj,keys){for(varpropinobj){if(obj.hasOwnProperty(prop)){varkeys_=keys.slice();// clone itkeys_.push(prop);if(typeofobj[prop]==='object'){unraveler(obj[prop],keys_);}else{collector.push({error: obj[prop],path: keys_});}}}}returncollector;}varfoo={"name":"cannot be blank","account":{"password":"cannot be blank","name":"cannot be blank"},"age":"not a number"};varerrors=unravelJSONObject(foo);for(vari=0,len=errors.length;i<len;i++){console.log(errors[i].path.join('.'));}
The results look like this:
name
account.password
account.name
age
The most efficient way to lookup a DOM element when you only know the last part of the element's name is via document.querySelector([id$=a]), but it isn't very accurate when you have multiple fields with the same name (eg. name and account.name) because you could match multiple elements (note that querySelector returns a single item, so it could potentially get the right one if the elements are in the correct source order, but who wants to depend on that?). Ideally, I'd use getElementById instead of querySelector since it is a more efficient function. In order to do that, I need some way to discerning the form's name without selecting all of the fields and examining each one for a prefix (which can be error prone if the designer is adding form fields with periods in the name just to mess with us).
Proposal
I would like to see an attribute added to the form by the dfForm splice that contains the name of the form. If our template looks like this:
<dfForm></dfForm>
And our form's name is "name", then the generated markup would look like this:
<formmethod="POST" data-df-name="form"></form>
For those not in the know, custom attributes are allowed in HTML5 by prefixing them with data-. I'm hesitant to suggest attaching it with the id, since I suspect many people are using it for other purposes and the name attribute was deprecated in HTML4.
From there, it would be a simple as making these modifications:
functionunravelJSONObject(obj,prefix){varcollector=[];unraveler(obj,prefix ? [prefix] : []);functionunraveler(obj,keys){for(varpropinobj){if(obj.hasOwnProperty(prop)){varkeys_=keys.slice();// clone itkeys_.push(prop);if(typeofobj[prop]==='object'){unraveler(obj[prop],keys_);}else{collector.push({error: obj[prop],path: keys_});}}}}returncollector;}varfoo={"name":"cannot be blank","account":{"password":"cannot be blank","name":"cannot be blank"},"age":"not a number"};// el is known in advance to be the form elementvarerrors=unravelJSONObject(foo,el.getAttribute('data-df-name'));for(vari=0,len=errors.length;i<len;i++){console.log(errors[i].path.join('.'));}
And now we have useful information to do an accurate check against the DOM:
If you've got a better way of attaching the form's name to the the form element, I'm all for it. It just needs to be on the form element for the best results. I realize this is something I could write a splice for myself, but it just seems like unnecessary boilerplate to write for every project. Plus, if there's an interest in this when I'm finished, I'd like to contribute it here -- so it has to be something I can depend on.
The text was updated successfully, but these errors were encountered:
I'd like to propose adding some hooks for JavaScript purposes when using Digestive Functors (not sure how much of this applies to non-Heist users). From a front-end perspective, the names of DF form fields have caused me a bit of trouble because I want to be able to write both my templates and my JavaScript to "just work" without having to hardcode things like form or subform names. Recently, I've been working on working with Digestive Aeson and would like to write an elegant solution that will go through the JSON response received from a submission made via XMLHttpRequest (AJAX) and match up the errors to the field they belong to. There's just one problem with that: Digestive Aeson doesn't tell you the form name.
Why this is a problem
Consider the following form:
Code to process the results (using Scotty):
Submitting with an empty JSON object returns the following information:
The problem becomes: how do I match the results to the fields via JavaScript? If I select all of the fields and split the names on the period character, I can traverse the JSON results and find the error:
However, it becomes inefficient to deal with results like this where the subform, which has no corresponding field, returns an error:
It would be more efficient to traverse the JSON result and check the DOM for fields that match (especially since it would be more common for the JSON object to be smaller than the collection of form fields). If they don't exist, then they get pushed into my global error pile.
The results look like this:
The most efficient way to lookup a DOM element when you only know the last part of the element's name is via
document.querySelector([id$=a])
, but it isn't very accurate when you have multiple fields with the same name (eg.name
andaccount.name
) because you could match multiple elements (note that querySelector returns a single item, so it could potentially get the right one if the elements are in the correct source order, but who wants to depend on that?). Ideally, I'd usegetElementById
instead ofquerySelector
since it is a more efficient function. In order to do that, I need some way to discerning the form's name without selecting all of the fields and examining each one for a prefix (which can be error prone if the designer is adding form fields with periods in the name just to mess with us).Proposal
I would like to see an attribute added to the form by the
dfForm
splice that contains the name of the form. If our template looks like this:And our form's name is "name", then the generated markup would look like this:
For those not in the know, custom attributes are allowed in HTML5 by prefixing them with
data-
. I'm hesitant to suggest attaching it with theid
, since I suspect many people are using it for other purposes and thename
attribute was deprecated in HTML4.From there, it would be a simple as making these modifications:
And now we have useful information to do an accurate check against the DOM:
If you've got a better way of attaching the form's name to the the form element, I'm all for it. It just needs to be on the form element for the best results. I realize this is something I could write a splice for myself, but it just seems like unnecessary boilerplate to write for every project. Plus, if there's an interest in this when I'm finished, I'd like to contribute it here -- so it has to be something I can depend on.
The text was updated successfully, but these errors were encountered: