How to set min validator if input value is less than min value? - angular8

I am trying to set min validator on formControl while initializing the control. but the thing is if the default input value is 10 and if we set Validators.min(15) then it's throwing ExpressionChangedAfterItHasBeenCheckedError.
This is the code snippet -
ngOnInit(){
// the default value is 10
this.fb.control(this.defaultValue, [Validators.min(15)]);
}

Related

Vue Select Component w/computed model doesn't show correct value under specific conditions

I've run into a computed property issue that I'm unsure how it should work. Here's the Issue Fiddle: https://jsfiddle.net/ibigpapa/6zgno1eu/4/
The problem is when the currently selected value is the Default value and I select the --reset-- option, I would expect the computed property to correctly reset the value to Default. Instead on the select box visually it stays on --reset--.
Now if you select another option so it's no longer the Default value. Then select the --reset-- option it will change the value and the select box visually back to Default.
How should you set this value in this instance?
I worked around the issue by hiding the option when the current value is the Default value. I still like to figure out if there is a way to do it fully inside the computed value.
Workaround Fiddle https://jsfiddle.net/ibigpapa/ou865d4x/12/
The computer property valueComp is based on value of data,the value is null in default,when you selected the --reset--,you reset the value to null again, the set of computer property valueComp will not work if the value have not changed,so the dom will not rerender,so you must find a way to change the value,here is the instance.
set: function (value) {
console.log(value)
if (value === '--reset--') {
this.value = '';
} else if (value === '') {
this.value = null;
} else {
this.value = value;
}
}

Vue.Js 2 Input formatting number

I have been struggling to get a number input to format numbers using vuejs2.
Migrating some view logic from asp.net core 2 to vue and I was using this:
<input asp-for="Model.LoanAmount" value="#(Model.LoanAmount > 0 ? Model.LoanAmount.ToString("N2") : String.Empty)" >
but that required me to reload that view onchange of the input.
I need a way to format number inputs with US format and 2 decimal places, (1,000,000.21) but to display nothing when the model value is zero or empty.
vue-numeric does ALMOST everything, but fails for me when I try to use a placeholder.
<vue-numeric v-model="vm.loanAmount" seperator="," placeholder=" " :precision="2" ></vue-numeric>
I tried using a space for placeholder because it crashes when I use an empty string.
This example displays 0.00 if zero or empty is inputted. I tried playing with the output-type and empty-value props.
I'm not wedded to vue-numeric but it is handy because I don't know of a more convenient solution.
You can achieve the formatting by simply using a computed property with separate getter and setter without the need for other dependencies.
computed: {
formattedValue: {
get: function() {
return this.value;
},
set: function(newValue) {
if (newValue.length > 2) {
newValue = newValue.replace(".", "");
this.value =
newValue.substr(0, newValue.length - 2) +
"." +
newValue.substr(newValue.length - 2);
} else {
this.value = newValue;
}
}
}
}
https://codesandbox.io/s/p7j447k7wq
I only added the decimal separator as an example, you'll have to add the , thousand separator in the setter for your full functionality.

DataTables - createdRow in conjunction with dynamic column hide/unhide

I implemented a dynamic column visibility to hide/show columns, e.g. DT.columns(5).visible(true) and DT.columns(5).visible(false) to show/hide column 5. I also have a callback for createdRow which let's say makes a html button out of the text in column 5.
Currently in createdRow I check this.api().columns(5).visible() and if true then I proceed to do $('td:eq(5)',row).html('<button>'+data[5]+'</button>') cell content, and if false then I return because otherwise I'd overwrite the current 5th <td> which is not the intended one. But then when I unhide column 5, it comes up as text since I did not run the previous code.
I'd like to be able to run the code and cache the html of the cell in column 5 so that when it's unhidden, it comes up with the intended <button>. What's the best way to do that? The column-visibility event?
Note that I know I can use the render: function (...) {} option for the column, but I do not want to use that because it affects the raw data of the table and affects filtering and searching - I want the raw data to remain unaffected, which is why I was using the createdRow or rawCallback callbacks.
Assume column 5 has visibile: false in the DataTable initialization object which looks like this:
var DT = $('#dt').DataTable({
...
createdRow: function (row, data) {
if (this.api().column(5).visible()) {
$('<button>' + data[5] + </button>')
.appendTo($('td:eq(5)',row).text(''));
}
);
Cheers
Look into using columnDefs and the 'render' function instead...
var DT = $('#dt').DataTable({
...
"columnDefs":[
{
'targets':[0],
'visible':false,
'render':function(data, type, row, meta){
...
}
]
});
https://datatables.net/reference/option/columns.render
https://datatables.net/reference/option/columns.data

Dynamically changing jQuery unobtrusive validation attributes

I have a page built in ASP.NET MVC 4 that uses the jquery.validate.unobtrusive library for client side validation. There is an input that needs to be within a range of numbers. However, this range can change dynamically based on user interactions with other parts of the form.
The defaults validate just fine, however after updating the data-rule-range attribute, the validation and message are still triggered on the original values.
Here is the input on initial page load:
<input id="amount" data-rule-range="[1,350]" data-msg-range="Please enter an amount between ${0} and ${1}">
This validates correctly with the message Please enter an amount between $1 and $350 if a number greater than 350 is entered.
After an event fires elsewhere, the data-rule-range is updated and the element looks as such:
<input id="amount" data-rule-range="[1,600]" data-msg-range="Please enter an amount between ${0} and ${1}">
At this point if 500 is entered into the input it will fail validation with the same previous message stating it must be between $1 and $350. I have also tried removing the validator and unobtrusiveValidation from the form and parsing it again with no luck.
$('form').removeData('validator');
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");
Is there a clean way to change the validation behavior based on the input attributes dynamically?
As Sparky pointed out changing default attributes dynamically will not be picked up after the validation plugin has been initialized. To best work around this without rewiring how we register validated fields and rules, I found it easiest to register a custom adapter in the unobtrusive library:
jQuery.validator.unobtrusive.adapters.add("amount", {}, function (options) {
options.rules["amount"] = true;
options.messages["amount"] = function () { return $(options.element).attr('data-val-amount'); };
});
jQuery.validator.addMethod("amount", function (val, el, params) {
try {
var max = $(el).attr('data-amount-max');
var min = $(el).attr('data-amount-min');
return val <= max && val >= min;
} catch (e) {
console.log("Attribute data-amount-max or data-amount-min missing from input");
return false;
}
});
Because the message is a function, it will be evaluated every time and always pick up the latest attribute value for data-val-amount. The downside to this solution is that everytime there is a change we need to change all three attributes on the input: data-amount-min, data-amount-max, and data-val-amount.
Finally here is the input markup on initial load. The only attribute that needs to be present on load is data-val-amount.
<input id="amount" data-val-amount="Please enter an amount between ${0} and ${1}" data-val="true">
You cannot change rules dynamically by changing the data attributes. That's because the jQuery Validate plugin is initialized with the existing attributes on page load... there is no way for the plugin to auto re-initialize after dynamic changes are made to the attributes.
You must use the .rules('add') and .rules('remove') methods provided by the developer.
See: http://jqueryvalidation.org/rules/
you can try this one:
// reset the form's validator
$("form").removeData("validator");
// change the range
$("#amount").attr("data-rule-range", "[1,600]");
// reapply the form's validator
$.validator.unobtrusive.parse(document);
charle's solution works! you cannot have model attributes to use it though, I build my inputs like:
#Html.TextBoxFor(m => Model.EnterValue, new
{
#class = "form-control",
id="xxxx"
data_val = "true",
data_val_range = String.Format(Messages.ValueTooBig, Model.ParamName),
data_val_range_max = 6,
data_val_range_min = 2,
data_val_regex_pattern = "^\\d+(,\\d{1,2})?$"
})
and then in javascript:
$("form").removeData("validator");
$("#xxxx").attr('data-val-range-max', 3)
$("#xxxx").attr('data-val-range-min', 0)
$.validator.unobtrusive.parse(document);

First initialization of a JSONStore Collection

So in Worklight, using JSONStore I want to initialize a collection the first time the app is ever loaded.
I want to fill it with a 'status' field with 36 instances of it. On the very first time the app is loaded I want to make all of these set to 0.
After this first initialization the app will update the status values from time to time based on user actions...
How do I initialize all the values at zero just the first time, and not again after that.
Thanks!
(and sorry if this question makes no sense..)
There's a count API you can use to get the number of documents in the collection. If that number is 0, it means it's the first time the collection was initialized, so you can add your 36 instances with status 0 there. For example:
WL.JSONStore.init(...)
.then(function () {
return WL.JSONStore.get('collection').count();
})
.then(function (numOfDocsInCollection) {
if (numOfDocsInCollection < 1) {
//this code will be reached only the first time the collection has been initialized
} else {
//this code will be reached every other time
}
});