JavaScript: dynamically changing values of data range rule - javascript

I have an input field that either allows negative and positive numbers, or only positive numbers based on a value of a select.
When changing the value of the select option, I'm trying to modify the rule of the input field like this:
const id = '#myId';
$(id).attr("data-val-range-min", -10000);
removeRules(id);
addRules(id);
$(id).change(); // trying to trigger the validation of the rule
The removeRules is a function:
let removeRules = function removeRules(field) {
$(field).rules('remove');
}
And so is the addRules:
let addRules = function addRules(field) {
let $field = $(field);
if ($field.attr("data-val-required")) {
$field.rules("add", {
required: true,
messages: {
required: $field.attr("data-val-required")
}
});
}
if ($field.attr("data-val-number")) {
$field.rules("add", {
number: true,
messages: {
number: $field.attr("data-val-number")
}
});
}
if ($field.attr("data-val-range")) {
$field.rules("add", {
range: [$field.attr("data-val-range-min"), $field.attr("data-val-range-max")],
messages: {
range: $field.attr("data-val-range")
}
});
}
}
When I change the select in the UI, the data-val-range-min attribute is set correctly, but the rule is not reapplied.
Only when I manually click into the input-field and deselect it again, the rule is applied...
What am I doing wrong here?
Thanks in advance

Only when I manually click into the input-field and deselect it again, the rule is applied...
There's a validation trigger you expect that isn't part of the plugin.
By default, this plugin triggers validation on:
onfocusout - when you leave an element
onkeyup - when you're typing inside a text box
onclick - interactions with radio, checkbox, and select
Adding and removing the rules though is not enough... you'll also need to force a validation test after adding or removing the rule.
Simply call the .valid() method on the element or form when you want to programmatically force validation. Since your OP contains zero HTML markup or working demo, I cannot be more specific with a solution.

Related

How do I stop the form submitting with invalid fields in a form?

I've been using this Background colors on Luhn Algorithm - JavaScript to help build a similar webpage. However unlike the original poster I would like the code not to submit if there is any invalid inputs across any of the fields. I would still like the input fields to change colour (either green for valid or red for invalid).
I believe that I can fix both the name and email using a mixture of pattern (for the name - "[A-Za-z!#$%&'*+-/=?^_`{|}~]+") and using the input type of email for the email section. This is in addition to using 'required' for all the input fields. However it is with the card section that I am having the most trouble with. At the moment, I cannot figure out a way to not allow the form to submit if the card field is red. For example using the code in the original post, I can input '1', the input field will turn red, but I can still submit the form. I am assuming it is something to do with the section below but I am not sure what to change/add:
cardNumberInput.addEventListener("keyup", e => {
const isCardValid = valid_credit_card(e.target.value);
if (isCardValid) {
cardNumberInput.style.backgroundColor = "green";
} else {
cardNumberInput.style.backgroundColor = "red";
}
})
Any help would be greatly appreciated and I apologise for any missing details that you may need, it is my first question here.
Make isCardValid global and add a submit event listener on your form like this
let isCardValid = false
const cardNumberInput = document.getElementById('your-input')
const cardForm = document.getElementById('your-form')
cardNumberInput.addEventListener("keyup", e => {
isCardValid = valid_credit_card(e.target.value);
if (isCardValid) {
cardNumberInput.style.backgroundColor = "green";
} else {
cardNumberInput.style.backgroundColor = "red";
}
})
cardForm.addEventListener('submit', e => {
if(!isCardValid)
e.preventDefault()
})
And the form won't be submitted until the isCardValid is true, if you want to submit the form manually instead of the default HTML submit behaviour, do this
yourForm.addEventListener(e => {
// To prevent default submission always.
e.preventDefault()
if(!isCardValid) return
// Do anything here...
})

Setting max value in cleave

I'm using cleave.js for a date input field in my Vue.js project.
The option that I passed was this:
<cleave :options="{
date: true,
datePattern: ['m', 'd','Y']
}" id="date-input" placeholder="MM/DD/YYYY" type="text"></cleave>
How do I set maximum value for Y ?
Cleave is an input formatting library and really nothing more. It's up to you to determine how you want to limit user input. Fortunately it offers an api for accessing the underlining raw input value. The API can be found here.
Youll need to write an event listener to check the users input and cap the value as you need.
I did that for card security number and working fine
const cardCCV = new Cleave("#cardCCV", {
numeral: true,
stripLeadingZeroes: false,
onValueChanged: function (e) {
const maxSize = 3;
if (e.target.rawValue.length > maxSize) {
cardCCV.setRawValue(e.target.rawValue.substring(0, maxSize));
}
},
});

How to reflect change made in a component's variable to the view in Angular 2?

I have (n) check boxes and a button in my angular2 view . When I click on one of them a function is called. When I click on the button every checkbox must be unchecked. How to do it?? (n) may vary dynamically.
enter image description here
I will give you an example from a table, since I have no idea what your code actually looks like, but it should work for what you need.
You need some object defined for all of your checkboxes. They likely all have certain properties in common, like labels. Here is an example of such an object:
myData = {
content: [
{
some_string: '',
some_number: 0,
type: '',
selected: false
}
]
};
With this object you can create checkbox instances and push each one to an array, which will hold all of your checkbox objects.
Create your checkboxes in your html in a loop using the objects you have defined above. In your html have your checkboxes call a function. In the case below the checkToggle() function is called.
<input id='{{row.id}}' class='bx--checkbox bx--checkbox--svg'
type='checkbox' name='checkbox' (change)="checkToggle($event,
row.id)" [checked]="row.selected">
checkToggle() has been defined as follows:
//select or deselect this check box
checkToggle(event, nodeId) {
const id = this.findNode(nodeId);
this.myData.content[id].selected = !this.myData[id].selected;
}
Your button should end up calling a function to check all of the boxes
<button (click)="checkToggleAll($event)">Your Button Title</button>
Finally, have your checkToggleAll() function go through the entire array of checkboxes and set them. Here is an example:
//select or deselect all the check boxes
checkToggleAll(event) {
for (let i = 0; i < this.myData.content.length; i++) {
if (this.controls[this.myData.content[i].type]) {
this.myData.content[i].selected = event.target.checked;
}
}
}
This is not something you can plug into your code but it should give you some idea of how to accomplish what you're after.

label inside combobox and conditional multiselect

I am building a pretty combobox with checkboxes and conditional entries. Everything works out alright, except for two features that I cannot figure out how to implement.
1) I would like to move the label inside the combobox, make it shift the values to the right, and appear in a slightly gray color.
2) I would like the value to ignore certain entries (group headers) selected. Those entries are there for functionality only - to select/unselect groups of other entries.
The entire project is in the zip file. You don't need a server, it's a client base app. Just download the archive, unpack, and launch app.html in your browser.
http://filesave.me/file/30586/project-zip.html
And here's a snapshot of what I would like to achieve.
Regarding your second issue, the best way I see is to override combobox onListSelectionChange to filter the values you don't want:
onListSelectionChange: function(list, selectedRecords) {
//Add the following line
selectedRecords = Ext.Array.filter(selectedRecords, function(rec){
return rec.data.parent!=0;
});
//Original code unchanged from here
var me = this,
isMulti = me.multiSelect,
hasRecords = selectedRecords.length > 0;
// Only react to selection if it is not called from setValue, and if our list is
// expanded (ignores changes to the selection model triggered elsewhere)
if (!me.ignoreSelection && me.isExpanded) {
if (!isMulti) {
Ext.defer(me.collapse, 1, me);
}
/*
* Only set the value here if we're in multi selection mode or we have
* a selection. Otherwise setValue will be called with an empty value
* which will cause the change event to fire twice.
*/
if (isMulti || hasRecords) {
me.setValue(selectedRecords, false);
}
if (hasRecords) {
me.fireEvent('select', me, selectedRecords);
}
me.inputEl.focus();
}
},
And change your onBoundlistItemClick to only select and deselect items in the boundlist not to setValue of the combo:
onBoundlistItemClick: function(dataview, record, item, index, e, eOpts) {
var chk = item.className.toString().indexOf('x-boundlist-selected') == -1;
if ( ! record.data.parent) {
var d = dataview.dataSource.data.items;
for (var i in d) {
var s = d[i].data;
if (s.parent == record.data.id) {
if (chk) { // select
dataview.getSelectionModel().select(d[i],true);
} else { // deselect
dataview.getSelectionModel().deselect(d[i]);
}
}
}
}
},
Regarding your first issue, it is easy to add the label using the displayTpl config option. But this will only add the text you need, without any style (grey color, etc). The combo is using a text input, which does not accept html tags. If you don't need the user to type text, than you may want to change the combo basic behavior and use another element instead of the text input.

java script mask problems

In js library use where .bind("focus.mask") and .bind("blur.mask") function which do blur and focus.
js library:
(function(a){var b=(a.browser.msie?"paste":"input")+".mask",c=window.orientation!=undefined;a.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},dataName:"rawMaskFn"},a.fn.extend({caret:function(a,b){if(this.length!=0){if(typeof a=="number"){b=typeof b=="number"?b:a;return this.each(function(){if(this.setSelectionRange)this.setSelectionRange(a,b);else if(this.createTextRange){var c=this.createTextRange();c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",a),c.select()}})}if(this[0].setSelectionRange)a=this[0].selectionStart,b=this[0].selectionEnd;else if(document.selection&&document.selection.createRange){var c=document.selection.createRange();a=0-c.duplicate().moveStart("character",-1e5),b=a+c.text.length}return{begin:a,end:b}}},unmask:function(){return this.trigger("unmask")},mask:function(d,e){if(!d&&this.length>0){var f=a(this[0]);return f.data(a.mask.dataName)()}e=a.extend({placeholder:"_",completed:null},e);var g=a.mask.definitions,h=[],i=d.length,j=null,k=d.length;a.each(d.split(""),function(a,b){b=="?"?(k--,i=a):g[b]?(h.push(new RegExp(g[b])),j==null&&(j=h.length-1)):h.push(null)});return this.trigger("unmask").each(function(){function v(a){var b=f.val(),c=-1;for(var d=0,g=0;d<k;d++)if(h[d]){l[d]=e.placeholder;while(g++<b.length){var m=b.charAt(g-1);if(h[d].test(m)){l[d]=m,c=d;break}}if(g>b.length)break}else l[d]==b.charAt(g)&&d!=i&&(g++,c=d);if(!a&&c+1<i)f.val(""),t(0,k);else if(a||c+1>=i)u(),a||f.val(f.val().substring(0,c+1));return i?d:j}function u(){return f.val(l.join("")).val()}function t(a,b){for(var c=a;c<b&&c<k;c++)h[c]&&(l[c]=e.placeholder)}function s(a){var b=a.which,c=f.caret();if(a.ctrlKey||a.altKey||a.metaKey||b<32)return!0;if(b){c.end-c.begin!=0&&(t(c.begin,c.end),p(c.begin,c.end-1));var d=n(c.begin-1);if(d<k){var g=String.fromCharCode(b);if(h[d].test(g)){q(d),l[d]=g,u();var i=n(d);f.caret(i),e.completed&&i>=k&&e.completed.call(f)}}return!1}}function r(a){var b=a.which;if(b==8||b==46||c&&b==127){var d=f.caret(),e=d.begin,g=d.end;g-e==0&&(e=b!=46?o(e):g=n(e-1),g=b==46?n(g):g),t(e,g),p(e,g-1);return!1}if(b==27){f.val(m),f.caret(0,v());return!1}}function q(a){for(var b=a,c=e.placeholder;b<k;b++)if(h[b]){var d=n(b),f=l[b];l[b]=c;if(d<k&&h[d].test(f))c=f;else break}}function p(a,b){if(!(a<0)){for(var c=a,d=n(b);c<k;c++)if(h[c]){if(d<k&&h[c].test(l[d]))l[c]=l[d],l[d]=e.placeholder;else break;d=n(d)}u(),f.caret(Math.max(j,a))}}function o(a){while(--a>=0&&!h[a]);return a}function n(a){while(++a<=k&&!h[a]);return a}var f=a(this),l=a.map(d.split(""),function(a,b){if(a!="?")return g[a]?e.placeholder:a}),m=f.val();f.data(a.mask.dataName,function(){return a.map(l,function(a,b){return h[b]&&a!=e.placeholder?a:null}).join("")}),f.attr("readonly")||f.one("unmask",function(){f.unbind(".mask").removeData(a.mask.dataName)}).bind("focus.mask",function(){m=f.val();var b=v();u();var c=function(){b==d.length?f.caret(0,b):f.caret(b)};(a.browser.msie?c:function(){setTimeout(c,0)})()}).bind("blur.mask",function(){v(),f.val()!=m&&f.change()}).bind("keydown.mask",r).bind("keypress.mask",s).bind(b,function(){setTimeout(function(){f.caret(v(!0))},0)}),v()})}})})(jQuery);
In my js file I want to unbind this .bind(focus.mask) and .bind(blur.mask) function ?
My Js:
function applyInputMasks() {
var $form.bind("blur.mask",function(){v(),f.val()!=m&&f.change()}) = $('form');
if ($form.size()) {
// added try catch so that if input field not found then it wont give an error
try{
//$form.find('input:not([skip-masks])[name*=cpf]').mask("999.999.999-99");
//$form.find('input:not([skip-masks])[name*=document]').mask("999.999.999-99");
$form.find('input:not([skip-masks])[name*=date]').mask("99/99/9999");
$form.find('input:not([skip-masks])[name*=postalCode]').mask("999999");
//$form.find('input:not([skip-masks])[name*=phone]').mask("999999999999");
// Postal code
var $postalCode = $form.find('input:not([skip-masks])[name*=postalCode]');
if ($postalCode.attr('skip-resolve-postalcode')) {
$postalCode.mask("999999");
} else {
$postalCode.mask("999999");
$postalCode.mask("999999", {completed: resolvePostalCode});
}
// override the value AFTER applying the mask
var valueToOverride = $postalCode.attr('override-value');
if (valueToOverride) {
$postalCode.val(valueToOverride);
}
} catch (e) {}
}
BRAPRINT.util.log('Masks applied!');
}
In my form where i use this mask function when I enter 6 digit postal code in box in submit form then city is automatically update If i providing incomplete pin code and clicking outside Postal Box in form data is cleared because in library use .bind("focus.mask") and .bind("blur.mask").
I read this tutorial:
http://view.jqueryui.com/mask/tests/visual/mask/mask.html
where say if .bind() convert to .unbind() then incomplete enter postal code in form not cleared after clicking out of the postal code input box.
after read this functionality I was try this in my js file where postal code :
$form.find('input:not([skip-masks])[name*=postalCode]').unbind("focus.mask");
$form.find('input:not([skip-masks])[name*=postalCode]').unbind("blur.mask");
and after this I was clearing all cache but this is not working.
I want data not cleared if i enter incomplete postal code. it is possible ?
I don't want to change in mask library file because this is not a right way.
Rather than unbind you could try e.preventDefault or return false as used in this article on CSS tricks which stops event propagation and bubbling.
http://css-tricks.com/return-false-and-prevent-default/

Categories