ngclass form validation to add a new class - angularjs

is it possible to check in ng-class whether if the myform.$valid then add a class?
I tried, so if the form is valid it will add the class "orange". Not sure if ng-class can do it like this or im just doing it wrong.
<input data-ng-disabled="vm.registerPassword != vm.registerConfirmPassword ? vm.registerPassword : disabled; registerForm.$invalid" disabled="disabled"
type="submit" id="submitForm" data-ng-click="vm.registerForm()" value="Register" class="btn-main orange maxw-200" ng-class="myform.$valid: 'orange'">
Here for the password condition:
data-ng-disabled="vm.registerForm.Password !== vm.registerForm.ConfirmPassword ? vm.registerForm.Password : disabled || registerForm.$invalid"

Yes it possibly. See in doc
In the case of a map, the names of the properties whose values are truthy will be added as css classes to the element.
ng-class="{'orange' : myform.$valid}"

Alternatively you can use a function, such as ,
ng-class="isValid(myform)"
and in your script...
$scope.isValid = function (frm){
if(frm.$valid == true)
return 'Orange'
else
return '';
}

Related

Prevent check of checkbox until function has been called

We are using AngularJS, and we require to run a function that determines whether or not the checkbox the user clicked on is actually checked. I have tried to pass $event on ngChange, but discovered it is unable to pass the $event object. The reason I want to access the $event object is so I could prevent the default behaviour until the required function has been called.
The code is as follows (does not include the code where I attempted to pass $event as it didn't work):
<label for="specificCase">
Yes
<input
type="checkbox"
name="specificCase"
data-ng-click="specificCase.no = false; specificCase.unsure = false;"
data-ng-model="specificCase.yes"
data-ng-change="$ctrl.specificCaseCheck('yes', specificCase.yes)">
</label>
<label for="notSpecificCase">
No
<input
type="checkbox"
name="notSpecificCase"
data-ng-click="specificCase.yes = false; specificCase.unsure = false;"
data-ng-model="specificCase.no"
data-ng-change="$ctrl.specificCaseCheck('no', specificCase.no)">
</label>
controller
function specificCaseCheck(value, boolean) {
//HERE I WANT TO PREVENT THE DEFAULT BEHAVIOUR OF THE CHECKBOX CHECKING
vm.optionSelected = !boolean ? false : true;
vm.caseSpecific = value == 'yes' && boolean ? true : false;
}
Question
How do I keep the checkbox unchecked until I have run a function in the controller?
Since you need to prevent default behavior but dont have the event you can follow the approach of this question Angular 2 Checkbox preventDefault
Basically you need to return false in your event handler to prevent the default behavior of "checking the checkbox when is clicked" then you can click it programatically
For that you can check this question Angular 4 checkbox set programmatically

Ternary Operator (Inline If without Else)

I have two checkbox in a <form>. The <form> have an onChange={this.checkBoxOnChange} assigned to it which fires up checkBoxOnChange(event){..} function on every change in the form. I am trying to map (Log) the status (ie whether they are checked or not). So, I've initially taken there value as false as they are not-checked then on each event I'm trying to change there value respectively (ie if false the true & vice versa).
On following this SO post I tried this:
(event.target.value=='BILLDED') && billed=(!billed)
By doing this I get:
Syntax error: Invalid left-hand side in assignment expression
Then I tried this:
(event.target.value=='BILLDED') ? (billed=(!billed)) : null
However, it gives me BILLED:true on every onChange (when clicked on BILLED checkbox)
This is code for checkbox inside render method:
render() {
return (
<div>
<form onChange={this.checkBoxOnChange}>
<input type="checkbox" name="invoicestatus" value="BILLDED" />BILLDED<br />
<input type="checkbox" name="invoicestatus" value="PENDING" />PENDING<br />
</form>
<ListData data={this.state.data}/>
</div>
);
}
This is the checkBoxOnChange() function within that same class (Component):
checkBoxOnChange(event){
var billed=false;
var pending=false;
// (event.target.value=='BILLDED') ? (billed=(!billed)) : null;
(event.target.value=='BILLDED') && billed=(!billed)
// (event.target.value=='PENDING') ? pending=(!pending) : null;
console.log("BILLDED:"+billed+" PENDING:"+pending);
}
What's wrong with the code?
Can I not use inline statement for this scenario?
Is there any better, more concise approach?
What's wrong with the code?
You initialise the billed variable inside your event handler to false, that's why you always get true instead of toggling a state.
Can I not use inline statement for this scenario?
You can, you just have to put the parenthesis in the right place:
(event.target.value == 'BILLDED') && (billed = !billed);
// ^
Is there any better, more concise approach?
Use a normal if statement. It's both shorter and more readable:
if (event.target.value == 'BILLDED') billed = !billed;
However, it gives me BILLED:true on every onChange (when clicked on
BILLED checkbox)
Is this not because you use a local variable as below
var billed=false;
which always starts as false?

How to add css class dynamically to input type html element in angular js controller function?

Requirement: Create a generic controller function in Angular JS that will cater to all the input types.
What you want then is to:
add the filled css class when the form field has a value, and
remove the filled css class when the form field doesn't have a value
do both of the above using a reusable function in an angular controller.
You can achieve this using Angular's built-in ng-class directive:
HTML:
<input
id="renewccCVV"
type="number"
class="form-control"
ng-class="isFilled(RenewCard.cvv)"
ng-model="RenewCard.cvv"
maxlength="4" />
JS:
$scope.isFilled = function(value){
return (!!value) ? "filled" : "";
}
Example Plunk
Add the below code to Angular js controller.
'filled' is the css class that I want to make use of. I am passing the $event from my ng-blur event in HTML input control.
$scope.addCssClass = function (event) {
if (event !== null && event.target !== null) {
if (event.target.value !== "") {
if (event.target.className.search('filled') < 0) {
var classes = event.target.className;
classes += ' filled';
event.target.className = classes;
}
}
else {
event.target.classList.remove('filled');
}
}
};
Here is the snippet of HTML code.
<input id="renewccCVV" type="number" class="form-control" ng-blur="addCssClass($event)" ng-model="RenewCard.cvv" maxlength="4" />
If my input control has value and css class 'filled' is not added to ng-class , then add the css class, if the input already has css class and value is not null, do not add the class. When the value from input control is removed, then remove the css class from the classList.

How can I validate an ng-repeated dropdown category selector?

I created a nested category model. In order to select a category for a product, you see a dropdown with the main categories. When you select one, a new dropdown is added to the right with the child categories to the one you selected. This repeats until you reach the last level. When this happens $scope.product.category_id is set. I want to invalidate the whole set of fields when $scope.product.category_id is null.
I've been using angular-bootstrap-show-errors for validation and I tried to mix it with ui-utils to achieve this one, using a custom function: validate_category().
Here's the HTML I used:
<span ng-repeat="parent_id in category_dropdown_parents" show-errors="{ skipFormGroupCheck: true }">
<select class="form-control" name="category_id"
ng-init="selected_category[$index] = init_select($index);"
ng-model="selected_category[$index]"
ng-options="category.name for category in (categories | filter : { parent_id: parent_id } : true ) track by category.id "
ng-change="select_category(selected_category[$index], $index)"
ui-validate="'validate_category()'" // added this to work with ui-utils
>
</select>
<span ng-if="$index+1 != category_dropdown_parents.length">/</span>
</span>
And this is my simple validation function:
$scope.validate_category = function() {
return ( $scope.product.category_id !== null
&& $scope.product.category_id !== undefined);
}
But this is not working. Ideas?
EDIT: I just realized, that the problem with this is that the validation function on ui-validate is executed after the ng-change function, so it's never able to check the $scope.product.category_id update.
Your select is using
ng-model="selected_category[$index]"
but the validation function is using
$scope.product.category_id
Shouldn't it be using
ui-validate="'validate_category($index)'"
and
$scope.validate_category = function($index) {
return($scope.selected_category[$index] !== null
&& $scope.selected_category[$index] !== undefined);
}
This is not the ideal answer but it's the best I could get. Shame on me, this was too simple:
<select class="form-control" name="category_id"
ng-init="selected_category[$index] = init_select($index);"
ng-model="selected_category[$index]"
ng-options="category.name for category in (categories | filter : { parent_id: parent_id } : true ) track by category.id "
ng-change="select_category(selected_category[$index], $index)"
required // !!!
>
</select>
That's it, just added the required attribute. The problem with this is that since the I'm not validating product.category_id but just validating all the dropdowns to be not empty. I guess I
'll have to rely on the code on select_category().

How to update ng-class based on ng-change?

I have an ng-repeat that creates several widgets, each with it's own select dropdown.
<div ng-repeat="item in widget.items" class="col-md-6">
<select ng-model="item.chosenTag"
ng-change="widget.updateTag(item)"
ng-class="widget.getButtonClass(item.tag, item.id)">
<option value="companies"
ng-selected="{{item.tag == 'companies'}}"
changed="companies">companies</option>
<option value="news"
ng-selected="{{item.tag == 'news'}}"
changed="news">news</option>
<option value="people"
ng-selected="{{item.tag == 'people'}}"
changed="people">people</option>
</select>
</div>
As the view is loaded, the ng-class="widget.getButtonClass(item.tag, item.id)" calls a function to check if 2 values are met, then sets ng-class to either btn-success or btn-default.
// This checks the view after load to change the class on each widget select
var vm = this;
vm.getButtonClass = function(tag, id) {
console.log('in getButtonClass');
if (tag && id) {
return 'btn-success';
} else {
return 'btn-default';
}
};
Next if the user now updates a select within any widget, ng-change will update to the correct value.
However I need to somehow re-run the ng-class check or rather just go ahead and add btn-success to the select without having to refresh the page.
How would you go about accomplishing this?
Is there a way to do something like this?
ng-class="{ functionToUpdateAll | boolean based on ng-change }"
Is there any specific reason that you need to call the function? Why dont you bind directly to those variables?
ng-class="'btn-success':item.tag && item.id, 'btn-default': !(item.tag && item.id)"
In that way you take advantage of mutual binding i.e. whenever the item.tag or item.id are changed, the class will be evaluated accordingly.
I suggest that instead of calling the function in ng-class, just assign it to a variable:
<select ng-model="item.chosenTag"
ng-change="widget.updateTag(item)"
ng-class="mySelectClass">
And in your updateTag function in the controller update that variable:
vm.updateTag = function(item) {
if (item.tag && item.id) {
vm.mySelectClass = 'btn-success';
} else {
vm.mySelectClass = 'btn-default';
}
};

Resources