Using required with a custom search/dropdown control - javascript

How do I enforce form requirement and validation on a custom form control in which the required data is not in a regular control?
I am using a custom user control called a Search and Select which can be found here, and although useful, it lacks some validation functionality. The control allows the user to do a typeahead search by typing into a textfield (#1), which then modifies a dropdown (#2). When an item in the dropdown (#3) is clicked, it becomes selected, causing the name of the item to also be displayed at the top (#4) and to have a checkmark displayed next to it in the dropdown list.
How can I enforce that an item has been selected on this control? Information that I've found on forcing the usage of require/ngRequire for custom controls comprised of other controls within it involve propagating the requireness of one of those inner controls - for example, making the whole Search control use the required status of the textbox contained within. However, this would be inaccurate - what is in the textbox is irrelevant, and whether something is selected is actually a matter of whether a behind-the-scenes local variable is set and whether its name is displayed in raw text.
I have attempted to modify the directive by requiring ngModel and modifying ngModel.$isEmpty. However, this does not appear to have any effect.
link: function (scope, elm, attr, ngModel) {
...
ngModel.$isEmpty = function(value) {
return (!scope.selectedItem || scope.selectedItem === {})
};
...
}
How can I force the requiredness of this field to be based off of the value of scope.selectItem?

Related

Typeahead value won't persist when updated with Javascript

Using twitter's typeahead library https://twitter.github.io, if you attempt to update an inputs value with javascript (or jQuery), the value is reset to its original value when the input is selected, and then you click away.
See this gif below
https://gfycat.com/tautsphericalirishdraughthorse
As you can see the typeahead form (with id team2) first contains the string randomstring
When updated with $("#team2").val("test") the change can be seen in the input, but when you select the input and then click away it resets.
Values only seem to persist if you select the box and type in the value.
I need a way where I can alter the value through a js command.

Get Input Field value using DTM on Submitting a form

I have two input fields that had the user access card and password. and the user click on submit button to authenticate.
I'm using DTM in my app to capture the user navigation but I want also to get the values of those field to my DTM so I would know who the user is.
And here is what I tried but with no luck.
Created Data element as below:
And created Event based rule. But not sure how to get the values to be shown in my report:
Thanks for your help.
Example Form
Since you did not post what your form code looks like, here is a simple form based on what I see in the screenshots you posted, that I will use in my examples below.
<form id='someForm'>
User Name <input type='text' name='userName'><br>
Password <input type='password' name='userPass'><br>
<input type='submit' value='submit' />
</form>
Data Elements
Okay first, let's go over what you did wrong.
1) You said you want to capture two form fields, but you only have one data element...maybe? You didn't really convey this in your question. I just assumed as much because of what you did throughout the rest of the screenshots. But to be clear: you should have two separate data elements, one for each field.
2) The CSS Selector Chain value you used is just input, so it will select the first input field on the page, which may or may not coincide with one of the input fields you are looking to capture. So, you need to use a CSS selector that is unique to the input field you want to capture. Something as simple as input[name="userName"] will probably be good enough (but I cannot confirm this without seeing your site). You will need to do the same for the 2nd Data Element you create for the other input field (e.g. input[name="userPass"])
3) In the Get the value of dropdown, you chose "name". This means that if you have for example <input type='text' name='foo'>, it will return "foo". Since you want to capture the value the user inputs, you should select "value" from the dropdown.
Solution
Putting all the above together, you should have two Data Elements that look something like this (one for the user name field and one for the password field; only one shown below):
Event Base Rule
Okay first, let's go over what you did wrong.
1) The value you specified in Element Tag or Selector is input. You aren't submitting an input field; you are submitting a form. Input fields don't even have a submit event handler! Your Event Type is "submit", so at a minimum, Element Tag or Selector should be form. But really..
2) Ideally, you should use a CSS Selector that more directly and uniquely targets the form you want to trigger the rule for. For example, maybe the form has an id attribute you can target in your CSS Selector. Or maybe the form is on a specific page, so you can add additional conditions based on the URL. What combination of CSS Selector or other conditions you use to uniquely identify your form depends on how your site is setup. In my example form above, I added an id attribute, so I can use form#someForm as the CSS Selector.
3) You checked the Manually assign properties & attributes checkbox, and then added two Property = Value items. This tells DTM to only trigger the rule if the input has a name attribute with value of "userName" AND if it has a name attribute value of "userPass". Well name can't have two values at the same time, now can it!
<input name='foo' name='bar'> <!-- bad! -->
All of this needs to be removed, because again (from #1), you should be targeting a form, not an input field.
4) For good measure, looks like you added a Rule Condition of type Data > Custom, but the code box is empty. The rule will only trigger if the box returns a truthy value. Since there is no code in the box, it will return undefined (default value returned by a javascript function if nothing is returned), which is a falsey value. This also needs to be removed.
Solution
Putting all the above together, the Conditions section of the Event Based Rule should look something like this:
But again, ideally your conditions should be more complex, to more uniquely target your form.
Referencing the Data Elements
Lastly, you can reference the input fields to populate whatever fields in the various Tool sections with the %data_element% syntax. For example, you can populate a couple of Adobe Analytics eVars like this (data element names reflect the examples I created above):
Or, you can reference them with javascript syntax in a custom code box as e.g. _satellite.getVar('form_userName');
Additional Notes
1) I Strongly recommend you do not capture / track this type of info. Firstly, based on context clues in your post, it looks like this may count as Personally Identifiable Information (PII), which is protected under a number of laws, varying from country to country. Secondly, in general, it is a big security risk to capture this information and send it to Adobe (or anywhere else, really). Overall, capturing this sort of data is practically begging for fines, lawsuits, etc.
2) Note that (assuming all conditions met), the "submit" Event Type will track when the user clicks the submit button, which is not necessarily the same thing as the user successfully completing the form (filling out all the form fields with valid input, etc.). I don't know the full context/motive of your requirements, but in general, most people aim to only capture an event / data on successful form completion (and sometimes separately track form errors).

Sitecore - Field not detected as modified. How to force the save prompt to show?

We are using the Taxonomy module for Sitecore: https://marketplace.sitecore.net/Modules/T/Taxonomy.aspx?sc_lang=en
The module works fine 90% of the time. The only catch is that when in a taxonomy field you select a value from the auto-complete options, the field doesn't seem to be marked as changed. This creates the occasional confusion with editors as when they publish the "Do you want to save?" prompt doesn't show and the content is published without tags.
If instead of selecting from the auto-complete we use the dialog box, everything works fine.
I looked at the markup, JavaScript and C# code and couldn't find a solution.
I even tried to set Sitecore.Context.ClientPage.Modified = true but it doesn't seem to do anything.
How can I force the save prompt to show?
I had a similar issue, I was updating a field using js and the experience editor wasnt detecting the change.
I got this working by doing the following using js:-
There is a save button state object saved in a view state field. You can grab by doing window.parent.document.getElementById("__SAVEBUTTONSTATE"). I then did the following:-
var saveButtonState = window.parent.document.getElementById("__SAVEBUTTONSTATE");
saveButtonState.value = 1;
saveButtonState.onchange();
This will make the save button enabled
In the experience editor, Sitecore wraps your sitecore item fields in an span element, which contain a unique id. (These are the fields you interact with in the experience editor). However, its not these values which Sitecore receives when you hit Save button. Sitecore actually stores values of your item fields in hidden inputs, so when you interact with the span element, in the background, these hidden inputs are being updated. So in order for Sitecore to receive your changes, you must update the corresponding hidden input. If you open Inspect element in the experience editor and search "scFieldValues", you will see these hidden inputs. I updated the field by using jquery:-
$('#scFieldValues').children('input').each(function () {
if (id.indexOf($(this).attr('id')) >= 0) {
$(this).val(value);
}
});
The id object is the id of the span element. The contents of that id is used in the id of the hidden input. This is why I use "id.IndexOf" to find correct input element. So when I update the span element value, I grab that value and update the corresponding input.
Hope this helps

What is the complete list of events supported by angular's updateOn property of ngModelOptions?

The docs say
updateOn: string specifying which event should the input be bound to. You can set several events using an space delimited list. There is a special event called default that matches the default events belonging of the control.
The page mentions a few events: blur, default, submit. Are there any others? Is the full list documented anywhere?
As far as i know, you can bind any available DOM event to the updateOn property. see a full list here.
Having a look at the Source of ngModel, you can see that the options passed to updateOn will get bound to the actual element itself.
https://github.com/angular/angular.js/blob/master/src/ng/directive/ngModel.js#L1188
Angular Source:
if (modelCtrl.$options.getOption('updateOn')) {
element.on(modelCtrl.$options.getOption('updateOn'), function(ev) {
modelCtrl.$$debounceViewValueCommit(ev && ev.type);
});
}
You can now control for a form (or single form elements) when the
value or the validity is updated. This feature has been available in
AngularJS 1.x but missed in Angular 2+ so far. The following update
options can now be used in Angular 5 forms:
change: change is the default mode. By using this update option the form / form control is updated after every single change.
blur: the blur change mode is only updated the from values / validity status after a form control lost the focus.
submit: updates are only done after form submit.
Full source is here.

Enable ASP.Net validator without immediately running validation

Question
Can I enable an ASP.Net validator without running validation immediately (i.e. giving the user a chance to input values before running it, but still force running validation on form submit)?
Background
I have a form that allows a person to input their family data when they check in their child(ren) into a public daycare system. We have five fields that I need to force parents to actively consider (allergies, special needs, etc). The values are not actually required, so too many parents were just skipping over the fields when their children should have had values specified.
My solution is to have a required field validator that's disabled if they click an N/A checkbox next to the textbox. (If someone has a better solution, I'm all ears; the UI of this form--which I inherited--makes me want to gouge out my eyes.)
The other thing is that when the "Add Family" button is clicked, four empty rows are auto-generated: two adults and two children. Whether a row represents a child or an adult is determined by a drop-down in that row. If "adult" is selected, or if the first name textbox in that row is empty, the validators are disabled.
The validators of all five fields are enabled as soon as both the drop-down selected value is "child" AND the first name textbox is not empty. The issue is that running ValidatorEnable() causes the form to validate. In the common case, the fields will be empty, since first name and "family role" (adult/child) will be inputted before whether that person has allergies or are potty trained. This means as soon as they input the name into a row specified as child, ASP.Net's all like "HEY, DUMMY, YOU HAVE AN INVALID FIELD!!!1!".
So, I would like to enable the validator, but prevent validation until the user actually either inputs an empty value into the allergy textbox, or they try to submit the form.
Is this possible?
Note, I would use a custom field validator, but validation isn't run on empty fields; afaik, only required field validators do that.
I've just adapted the answer here: http://veskokolev.blogspot.co.uk/2007/11/how-to-disable-validation-group-with.html to enable some validators client-side with jQuery. Once they were enabled, the validation function did run - I don't know how to stop it (without modifying the ASP.NET JS code, which I guess is an option?); so I simply hid the messages until the validation is run again (which is easy enough with $(x).hide()).
Considering all the client-side code does is show the warning and stop you submitting I think this is OK. The usual things that will cause the validator to re-run will re-show the message.
So if I have validators like:
<asp:Validator runat="server" CssClass="js-validator-set-a" />
I can use this Javascript:
toggleValidators('.js-validator-set-a', true);
function toggleValidators(selector, enable) {
// get the page validators into a jQuery object
var vals = getJqueryObjectFromArrayOfEls(Page_Validators)
vals.filter(selector).each(function (i, o) {
ValidatorEnable(o, enable);
$(o).hide();
});
};
function getJqueryObjectFromArrayOfEls(elsArray) {
var x = $();
$.each(Page_Validators, function (i, o) {
x = x.add($(o));
});
return x;
}
I just came across a similar requirement. WhatI did was first to set a valid value to the compnent to be validated, then enable the validator and finally I cleared the value in the component again. Something like
$('#<%= tbxValue.ClientID %>').val('X'); // set a value to the textbox
ValidatorEnable(<%= rfvValue.ClientID %>, true); // enable the required field validator
$('#<%= tbxValue.ClientID %>').val(''); // clear the value from the textbox
Yes, it's possible in a variety of ways. The two most common and perhaps sensible things to do are :
Have validation occur completely in the code-behind via code only
Have ASP.NET validators that are set to enabled=false and then turn them on and call Page.Validate()
Instead of using that function, you can make your own function that has some of the same code as ValidatorEnable, but wont trigger the validation.
function myValidatorEnable(val, enable) {
val.enabled = (enable != false);
}

Categories