Angular - Watching a form whether its $dirty - performance - angularjs

In my Angular app, I'm setting the placeholders in my form through some code in the controller (showing particular text for particular times of day).
When a user begins typing into any field of that form, I want all placeholders to be cleared.
To do this I understand I need to use $dirty using $watch
$scope.$watch('myForm.$dirty', function() {
//clear the placeholders
}, true);
My question is watch quite performance intensive in this situation or is there a more optimised way?
Thanks.

If you use $dirty and $watch it will work but it will clear all placeholders before you begins type or on controller load.
So, you can try this its work for me.
<div ng-controller="Ctrl">
<input type="text" ng-model="name1" ng-change="change()" placeholder={{placeholder1}}>
<input type="text" ng-model="name2" ng-change="change()" placeholder={{placeholder2}}>
<input type="text" ng-model="name3" ng-change="change()" placeholder={{placeholder3}}>
</div>
function Ctrl($scope) {
$scope.placeholder1="name";
$scope.placeholder2="city";
$scope.placeholder3="address";
$scope.change=function() {
$scope.placeholder1="";
$scope.placeholder2="";
$scope.placeholder3="";
};
}

Related

Angular: Disable button on click after required fields are filled in the form

I need to disable the submit button after clicking on the button to prevent multiple submissions but before the it has to ensure that the required fields are filled.
I tried
<body ng-app="ngToggle">
<div ng-controller="AppCtrl">
<form name="newUserForm">
<input type="text" required>
<input type="text" required>
<input type="text">
<button ng-click="disableClick()" ng-disabled="isDisabled"
ng-model="isDisabled">Disable ng-click</button>
</form>
</div>
</body>
angular.module('ngToggle', [])
.controller('AppCtrl',['$scope', function($scope){
$scope.isDisabled = false;
$scope.disableClick = function() {
alert("Clicked!");
$scope.isDisabled = true;
return false;
}
}]);
but this will only disable the button without any validation
Ok, I get what you mean/want so I'll try to help and come up with some code - which is obviously missing but if it wasn't missing the necessary code, you'd have the solution :)
First, you'll have to properly write your form:
<form name="newUserForm" ng-submit="disableClick(newUserForm.$valid)" novalidate>
<input type="text" name="input1" ng-model="form.input1" required>
<input type="text" name="input2" ng-model="form.input2" required>
<input type="text" name="input3" ng-model="form.input3"> //not required
<button type="submit" ng-disabled="isDisabled">Disable ng-click</button>
</form>
so what we've got here, which you're missing:
You did name your form, but you're missing a submit, in the form as ng-submit or the button with type="submit", which will submit the form and that's when the validation happens
In order for Angular to validate your inputs, they need to have ng-model, otherwise it will not validate (HTML5 validation would, but read on)
I've added novalidate so we tell the browser "Hey, we need this validated but not by you, so do nothing", and Angular takes over
And last but not least, Angular adds a couple of properties to the form (see more here: Angular form Docs), $valid being one of them, which is set to true when all validated inputs are valid.
So this sums up the changes you needed to do to your form.
As for the Javascript part, there is just one small change:
$scope.disableClick = function(valid) {
if(valid && !$scope.isDisabled) {
$scope.isDisabled = true;
}
return false;
}
I guess the change is obvious, but I'll explain anyway - check that newUserForm.$valid (boolean) and if it's true (meaning form has passed validation) disable this button.
Of course, you'll have to add checks not to run the code on any type of submits and not just disabling the button (which can easily be re-enabled via Dev Tools), so that's why I added !$scope.isDisabled to the if statement.
Hope this answers your question :)
P.S. Here's a running demo in Plunker

How to get the uib-popover to open or close when the focus of the input field changes

I have a input field that has the uib-popover control on it. I have followed the documentation on how to get the directive to open but I have noticed some discrepancies in the documentation as well as examples on plnker and SO questions here.
Within my hmtl I have the inputs set as follows:
<div class="form-group col-xs-6 col-sm-6 col-md-6 col-lg-6">
<label>Password</label><input type="{{user.inputType}}" ng-blur="user.validatePassword(user.newUser.password, user.newUser.confirmPassword)" placeholder="Enter Password" id="password" required class="form-control" ng-model="user.newUser.password" uib-popover-template="'myPopoverTemplate.html'" uib-popover-trigger="'focus'"/>
</div>
<div class="form-group col-xs-6 col-sm-6 col-md-6 col-lg-6">
<label>Confirm Password</label>
<input type="{{user.inputType}}" ng-keyup="user.validatePassword(user.newUser.password, user.newUser.confirmPassword)" placeholder="Confirm Password" id="confirmPassword" required class="form-control" ng-model="user.newUser.confirmPassword"/>
<span style="color: red">{{user.message}}</span>
</div>
Most examples as well as the SO questions on here are using an older library as attributes are not prefaced with uib-*.
This code/directive currently works and renders but it only work or appears when clicking in the field and then clicking in the same field to close the popover. I have tried both the focus trigger and the oustsideClick trigger. Both have the same result of not rendering or closing the popover unless clicking in the field.
versions of the frameworks used are:
angularjs 1.5.8
ui-bootstrap 1.3.3
Changing the trigger to match earlier examples were popover-trigger is used vs. uib-popover-trigger is used disables the popover
I have created a working plunker that demonstrates what is happening.
Any suggestions on what I am missing or what I need to change.
Thanks in advance
According to tooltip.js description, in order to set a custom trigger,
it needs to be specified via trigger option passed to the $tooltipProvider.options method. In your case for focus trigger it will be:
app.config(['$uibTooltipProvider', function ($uibTooltipProvider) {
$uibTooltipProvider.options({ trigger: 'focus' });
}]);
Updated plunker that shows how to trigger tooltip on focus handler.
There's a problem of your code, please modify like below:
app.js:
(function() {
var app = angular.module('app', ['ui.bootstrap']);
app.controller('main',[ '$scope', main]);
function main($scope)
{
vm = this;
vm.message = 'hello';
vm.dynamicPopover = {
content: 'Hello, World!',
templateUrl: 'myPopoverTemplate.html',
title: 'Title'
};
}
}());
index.html
<input class="form-control" uib-popover-template="vm.dynamicPopover.templateUrl" popover-trigger="focus"/>
Actually, you can not just pass the template's id to the uib-popover-template attribute, you need to create an object to map it waited to pass.

How do I submit a form when input ng-change in AngularJS

What is the "AngularJS way" of doing a form submit when any of its inputs have been clicked (or changed)?
<form ng-submit="submit($event)" id="myForm">
<input type="checkbox" name="foo" value="bar" ng-click="???"/>
</form>
I'm tempted to use jQuery and simply doing ng-click="$('#myForm').submit()", but it's probably worth learning it properly.
I have tried doing ng-click="submit($event)", but the error here is the $event object within the scope of the input instead of the entire form (correct me if I'm wrong, this is what I'm getting from the documentation).
Well, you can do something like this for sure by triggering the AngularJS submit event:
$scope.change = function($event) {
$timeout(function() {
angular.element($event.target.form).triggerHandler('submit');
});
};
where
<input type="checkbox" name="foo" value="bar" ng-click="change($event)" />
However I think it's better to simply use the same function in ngClick as used in ngSubmit.
Demo: http://plnkr.co/edit/tJIYD9ZVjYzwA2aXJobo?p=preview
ng-change is what worked for me using a text input:
<form>
<select data-ng-model="headerName" data-ng-options="header for header in headers"
data-ng-change="calculateCorrelations()"></select>
</form>

Detecting value change in ng-model without using $watch and form for application having large number of models

My application has a lot of models in the page. I want to detect whether user has changed value of any model on click of save. Using $watch on every model puts too much load, so don't want to use this method. Is there any good approach for this?
Small snippet is like below:
<div>
<div class="ttere2">
<input type="radio" name="nc2-radio3" ng-model="nc2PenaltyAfter" value="specificDays" />
<input class="ggfe1" ng-model="nc2AfterDays" ng-disabled="nc2PenaltyAfter!='specificDays'" type="number" min="1" max="100" step="1" value="1" />days</div>
<div class="admin_wp-line">
<input type="radio" name="nc2-radio3" ng-model="nc2PenaltyAfter" value="immediately"/> Immediately </div>
<div class="acfv1">model 1</div>
</div>
<div style="margin-top: 20px;"><button ng-click="saveData();">Done</button></div>
............too many inputs go here
</div>
Use .$dirty! Angular will set this on every element that is bound using ng-model, automatically, when it has been changed. It will also set it on the entire form. You can access it in code like this:
if ($scope.myForm.$dirty) {
// Your code here
}
Angular will provide six useful variables on the form, and every ngModel-bound element in your form: $dirty and $pristine, $valid and $invalid, and $touched and $untouched. You can mix and match these to drive a lot of useful behaviors, and they're available both in your controller (using the expression shown above) and your template (directly).

Get "raw" value from invalid input field

I have an input field in a form with some validations. It works like a charm.
It basically looks like this:
<input
class="form-control"
type="number"
ng-model="zipcode"
ng-minlength="5"
ng-maxlength="5"
id="zipcode"
name="zipcode"
required
>
A working plunkr is here: http://plnkr.co/edit/H0h59kG75T5MGE9cAhSo?p=preview
But now I also want to react to every input change - whether valid or not. So for example if the input field contains "123" it is not valid and the value is not transferred to my model - thats fine. But I still want to get the value to do some intermediate requests to a webservice.
Any Ideas?
First call the form element in your controller, then use the $viewValue attribute :
View :
<form name="form">
<input
...
ng-model="zipcode"
ng-change="getRawValue(form)"
name="zipcode"
required
>
</form>
Controller:
$scope.getRawValue = function(form) {
var rawValue = form.zipcode.$viewValue;
}
Angular 1.3 introduced a real answer for this: allowInvalid in ngModelOptions.
Example:
<input
type="text"
name="userName"
ng-model="user.name"
ng-model-options="{allowInvalid: true}"
>
Here is what i came up with for your scenario.
Basically you can write a directive which requires ngModel (ngModelController). The ngModelController has a array of parsers which it call to parse the view value in a pipeline manner. If validation fail these parsers do not update the model. If you inject a custom parser at the start of this parsers array, you can get the each view change value and do anything you want with it.
See my plunkr here http://plnkr.co/edit/ruB42xHWj7dBxe885OGy?p=preview (See console)
The basic code would be
ngModelCtrl.$parsers.splice(0,0,(function (viewValue) {
console.log("The view value is:"+viewValue)
return viewValue;
}));
Also see ngModelController documenation

Resources