Firing ng-change only once - javascript

I need to call a function from ng-change on an input of type text only once, and on the first call it sets a boolean value to true, after that i want to disable the ng-change from firing whenever the input changes because all i need to do is to change a boolean to true
here is the controller
angular.module("app",[]).controller('FieldCtrl',['$scope',function($scope){
$scope.Value = '';
$scope.IsRequired = true;
$scope.HasBeenForTheFirstTime = false;
$scope.ValueChanged = function() {
$scope.HasBeenForTheFirstTime = true;
console.log("isFired");
};
}]);
and the html simply
<input type="text"
ng-model="Value"
value="{{Value}}"
ng-change="ValueChanged()">
one more thing is, is using ng-change the right thing in this case?

Using $watch...
angular.module("app",[]).controller('FieldCtrl',['$scope',function($scope){
$scope.Value = '';
$scope.IsRequired = true;
$scope.HasBeenEditedBefore = false;
$scope.UnWatch = $scope.$watch("Value",function(){
if($scope.Value.length > 0)
{
$scope.HasBeenEditedBefore = true;
$scope.UnWatch();
}
});
}]);

you can remove $scope.ValueChanged function and use the following code is enough.
<input type="text"
ng-model="Value"
value="{{Value}}"
ng-change="HasBeenForTheFirstTime=true" />

Related

Make invalid form immediately after loading

I have a simple form written in AngularJS.
I would like to make the form invalid immediately after loading. Unfortunately $scope.myForm.$valid = false; doesn't want work. Do you have any other technique to do it? It is important for me as I want to let user click the button only when he/she choose at least on checkbox. Now you can submit the form always after loading the form.
<form name="myForm" ng-submit="myForm.$valid">
<input type="checkbox" ng-model="obj.first" ng-change="onChange()" /> First <br />
<input type="checkbox" ng-model="obj.second" ng-change="onChange()"/>Second <br />
<input type="checkbox" ng-model="obj.third" ng-change="onChange()"/> Third <br>
<button type="submit" ng-disabled="!myForm.$valid" ng-click="click()">test</button> <br>
</form>
$scope.myForm = {};
$scope.myForm.$valid = false;
$scope.click=function () {
console.log('-------------2', $scope.myForm);
};
$scope.onChange=function () {
console.log('before:', $scope.myForm);
var isValid = false;
angular.forEach($scope.obj, function(value, key) {
if(value == true){
isValid=true;
}
console.log(key + ': ' + value);
});
if(!isValid){
$scope.myForm.$valid = false;
$scope.myForm.$error.checkBoxes = {
isChecked: false
};
}
console.log('after:', $scope.myForm);
}
So this is my final solution, the form in the scope has a function called $setValidity() where we can change the validity state, and notify the form. Refer here, so I check if any of the checkboxes are having true value, then I set the value for one checkbox alone as true, if not then one of the checkboxes with name one is set to $valid = false, thus the entire form will be invalid, please go through my code for the implementation of the solution!
JSFiddle Demo
JS:
var app = angular.module('myApp', []);
app.controller('MyController', function MyController($scope) {
$scope.onChange = function() {
if ($scope.obj) {
if ($scope.obj.first || $scope.obj.second || $scope.obj.third) {
$scope.myForm.one.$setValidity("Atleast one checkbox needs to be selected", true);
} else {
$scope.myForm.one.$setValidity("Atleast one checkbox needs to be selected", false);
}
} else {
$scope.myForm.one.$setValidity("Atleast one checkbox needs to be selected", false);
}
}
});
Try this in your submit button. hope it works
data-ng-disabled="myForm.$submitted || myForm.$invalid && !myForm.$pristine"

angular js - ng-change not working for checkbox with make switch class

Html View:
<input type="checkbox"
id="checkbox1"
class="make-switch"
ng-init="option=true"
ng-change="getInput(option)"
ng-model="option"
data-on-text=" Individual "
data-off-text=" Company " input >
Controller file:
$scope.getInput = function(option){
alert(option);
}
I am using the checkbox with make-switch class. It's not getting fired. The ng-change directive is not affecting any changes.
Simply, initialize your option variable in your controller, like this:
$scope.option = false;
angular.module('MetronicApp').controller('leadDetailsController', function($rootScope, $scope, $http, $timeout) {
$("[name='makeSwitch']").bootstrapSwitch();
$scope.select = true;
$scope.leadSelect = false;
$scope.option = false;
//Next Click
$scope.nextView = function(leadSelect){
$scope.select = false;
$scope.Individual = true;
}
$scope.getInput = function(option){
alert(option);
}
});

Validate the input field for existing item in object array?

in my todo list i dont want user to input same todos again again...
but my problem is, when i enter something for example (test) first time and than i enter (test2) and than i enter (test) again, so its taking a value.... how to validate properly....
fiddle
https://jsfiddle.net/LaL7h6Lv/1/
html
<div ng-app="todoApp" ng-controller="mainCtrl">
<ul>
<li ng-repeat="todoItem in todoItems">{{todoItem.name}}</li>
</ul>
<form ng-submit="addItem()">
<input type="text" ng-model="newItem">
<input type="submit" name="go">
</form>
</div>
angularjs
angular.module("todoApp", [])
.controller('mainCtrl', ['$scope', function($scope){
$scope.todoItems = [{'name' : 'akshay'}];
$scope.test = false;
$scope.addItem = function(){
if($scope.newItem){
$scope.checkRepeatTodo();
if($scope.test == true){
$scope.todoItems.push({'name':$scope.newItem});
$scope.newItem = '';
}else{
alert('same todo');
$scope.test = false;
}
}else{
alert('fill the form');
}
};
$scope.checkRepeatTodo = function(){
$scope.todoItems.filter(function(item){
if($scope.newItem === item.name){
$scope.test = false;
}else{
$scope.test = true;
}
});
};
}]);
The issue is with the $scope.test value, you override the value to true when it filters down the 3rd item.
See the Working fiddle
Alternative:
Make a javascript function rather than one in $scope and call that function return if its a valid entry or not.
This eliminates the need to have $scope.test and $scope.checkRepeatTodo as they do nothing of importance.
function checkRepeatTodo() {
var valid = true;
$scope.todoItems.filter(function(item){
if($scope.newItem === item.name){
return valid = false;
}
});
return valid;
};
And use the same as:
if(checkRepeatTodo()){
$scope.todoItems.push({'name':$scope.newItem});
$scope.newItem = '';
}
else{
alert('same todo');
}
Demo here

How to change CSS in Controller

I m trying to do a workaround for a bug. i need to just change the css of an element when an other checkbox is clicked. But it is not working.. It just works when i click on an other button somewhere else but when i click on the checkbox the view is not being refreshed maybe ?
Any ideas ?
View:
<input
type="checkbox"
value="application.callback" id="telefonBox"
ng-click="application.callback = !application.callback; toggleClass(application.callback)"
/>
Controller:
$scope.toggleClass = function(newValue) {
var element = angular.element(document.querySelector('#additional'));
if (newValue) {
element.toggleClass("tooltip-agent tooltip-agentChecked ");
} else {
element.toggleClass("tooltip-agentChecked tooltip-agent");
}
$scope.$apply();
}
i tried this to but not working
$scope.$watch('$scope.application.callback', function (newValue, oldValue) {
var element = angular.element(document.querySelector('#additional'));
if (newValue) {
element.toggleClass("tooltip-agent tooltip-agentChecked ");
} else {
element.toggleClass("tooltip-agentChecked tooltip-agent ");
}
add ng-modal into checkbox
<input type="checkbox" ng-model="application.callback">
and ng-class into your #additional element
<div id="additional" ng-class="{true:'tooltip-agent tooltip-agentChecked', false:'tooltip-agentChecked tooltip-agent'}[application.callback]"></div>
DEMO
You should not manipulate elements in angular as much as possible, you can do it easier with ng-class like this
<div id="test" ng-class='{ active: vm.isChecked }'>
lorem
</div>
ng-class accepts an object as parameter, in this case it's { active: vm.isChecked } which mean if vm.isChecked evaluates to true, the active class will be applied to the element
$scope.selection = function($event) {
var checkbox = $event.target;
var action = (checkbox.checked ? 'check' : 'uncheck');
if(action == "check")
angular.element(document.querySelector('#additional')).addClass("tooltip-agent tooltip-agentChecked");
else
angular.element(document.querySelector('#additional')).addClass("tooltip-agentChecked tooltip-agen");
};
});
<input type="checkbox" id="additional" ng-model="check" ng-click="selection($event)" >

Date input validation using ng-change, AngularJS

I's using AngularJS and AngularJS bootstrap in my page. I have a date picker directive that looks like this:
<div class="form-group {{dateStatus.class}}">
<p class="input-group">
<input type="text" id="inpDate" class="form-control"
datepicker-popup="dd-MMMM-yyyy" ng-model="task.date"
is-open="datePickerStatus.isOpen" min-date="minDate"
datepicker-options="dateOptions" ng-required="true"
close-text="Close" placeholder="Due date"
ng-change="checkDateValidity()"
/>
<span class="input-group-btn">
<button type="button" class="btn btn-default"
ng-click="openDatePicker($event)"
>
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
</p>
</div>
To validate the date input, in my controller I have the following function:
$scope.checkDateValidity = function(){
var date,
isValid,
taskDate;
taskDate = $scope.task.date;
date = new Date(taskDate);
isValid = !isNaN(date);
if(isValid) {
$scope.addButtonState.isOk = true;
$scope.dateStatus.class = '';
}
else{
$scope.addButtonState.isOk = false;
$scope.dateStatus.class = 'has-error';
}
}
everything works fine for checking if the date inserted is valid, but the problem is that when the date input is left blank(or changed from a valid state to blank)
I want it to be acceptable too, but since both empty input and invalid date are undefinedI don't know how to declare between the cases.
I also thought of reading the input text directly like this:
document.getElementById('inpDate').value
but the ng-change is fired when the value is changed and I'm left with the previous value which is useless now...
thanks for your time and response.
A much better way of validating is using a directive to add a Validation Rule.
.directive("validateDate", function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$validators.validateDate = function(modelValue, viewValue) {
if(!isNaN(modelValue) || ctrl.$isEmpty(modelValue)){
return true;
}
return false;
};
}
};
})
then you just need to add validate-date to the input tag and the validation will mark the input as valid if it is !isNaN (when the date is a number OR is empty)
You can easily validate #inpDate value by binding validator callback to both change and keyup events, then when your callback triggered you can check the validity of your input.
$timeout(function(){
angular
.element(document.getElementById('inpDate'))
.bind('keyup change', function(){
var inputValue,
customDate,
isValid;
inputValue = this.value;
if(inputValue != ''){
customDate = new Date(inputValue);
isValid = !isNaN(customDate);
if(isValid){
console.log('Valid');
// do something
}
else{
console.log('Invalid');
// do something else
}
}
else{
console.log('Empty');
// do something else
}
});
}, 400);
Please make sure that your have injected $timeout in your controller.
If you want to validate like that, then you can use
if(document.getElementById('inpDate').value === "" ){
$scope.addButtonState.isOk = true;
$scope.dateStatus.class = '';
}
this at the beginning of the $scope.checkDateValidity function

Categories