how to hide value of input element if its $pristine - angularjs

I have ng-model attached to , but i want to display a default placeholder value if it's not been touched ($pristine). Is there any good way to do it? I cannot simply set my ng-model value to null during initial.
Here's my plunker:
http://plnkr.co/edit/0kzKrwKTbJzsMGG8D1gQ?p=preview
<body ng-controller="inputController">
<input type="number" id="pricefield" min="0" name="price" placeholder="Price" ng-model="test.value" required/>
</body>
angular.module('plunker', []);
function inputController($scope) {
$scope.test = {value: 0};
}

You could use ng-attr directive to set placeholder value dynamically, to check the form element is pristine or not you need to place this field inside a form & then you could easily check the $pristine property of that form element like myForm.price.$pristine.
Markup
<form name="myForm">
<input type="number" id="pricefield" min="0" name="price" ng-model="test.value"
ng-attr-placeholder="{{myForm.price.$pristine ? 'Some Value': 'Default Value'}}" required/>
</form>
Demo Plunkr
Update
I'd suggest to have one directive that will change hide the $viewValue on initial load & will show placeholder. Directive will have controller over the display value using $formatters on ngModelControlller
Markup
<input type="number" custom-dir id="pricefield" min="0" name="price"
ng-attr-placeholder="{{myForm.price.$pristine ? 'Initial Placeholder': 'After change Placeholder'}}"
ng-model="test.value" required/>
Directive
app.directive('hideInitialLoad', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attr, ngModel) {
var initalHide = true;
//format text going to user (model to view)
ngModel.$formatters.push(function(value) {
console.log(attr.min > value)
if (initalHide){
initalHide = false;
return undefined;
}
return value;
});
}
};
});
Updated Demo

Related

AngularJs - show-hide password on click event using directive

I have one input field for password and one button with that input field
now, if type of input field is passwordi.e type="password", then on click of that button it should become text i.e type="text"
if again I click on the same button it should change type="password"
Means it should toggle the value of type of input element
I have done this using controller, It's working fine with controller. below is the working code using controller
But instead of controller if i want to use directive then how to handle this toggle condition using directive
purpose - I want to use this functionality on multiple input elements
HTML
<div class="input-group">
<label>Password</label>
<input type="{{inputType}}" class="form-control" ng-model="password" />
<span ng-click="show()">show</span>
</div>
Controller
$scope.inputType = 'password';
$scope.show = function() {
if ($scope.inputType === 'password') {
$scope.inputType = !$scope.inputType;
$scope.inputType = 'text';
} else {
$scope.inputType = !$scope.inputType;
$scope.inputType = 'password';
}
}
I tried using Directive - Below is my trial code
I am not getting how to change the type of <input /> element using directive
Directive
.directive('myDir', function() {
require: 'ngModel',
link: function (scope, element, attrs) {
console.log(attrs.type);
attrs.type = 'password'
// how to call this below code on click event or on click of <span>
which I am using for password
if (attrs.type === 'password') {
attrs.type = !attrs.type;
attrs.type = 'text';
} else {
attrs.type = !attrs.type.inputType;
attrs.type = 'password';
}
}
})
HTML Using Directive
<div class="input-group">
<label>Password</label>
<input my-dir type="" class="form-control" ng-model="password" />
<span ng-click="show()">show</span>
</div>
You can use ng-attr-type directive for dynamically change the input type. For example:
<input ng-attr-type="{{ isPassword ? 'password' : 'text' }}">
you can change the value of isPassword to the click event and make it toggle.
Using directive
.directive('isPassword', function() {
return {
restrict : 'A',
scope: {
isPassword: '=isPassword'
},
link: function (scope, element, attrs) {
scope.$watch('isPassword', function(a, b){
element.attr('type', a ? 'password' : 'text')
})
}
}
});
<input is-password="checkPassword" placeholder="Put your password" />
<input type="checkbox" ng-model="checkPassword" />
update on button click
<button ng-click="checkPassword=!checkPassword">click</button>
This is what the following directive does when added to the input element.
It appends a span element "Show me" with ng-click=show() event attached to it.
scope: true enables an isolated scope for the directive. This makes sure the function show() is unique for each directive.
When clicked on "Show me", the directive changes the input type of that element.
Hope this helps.
JSfiddle link

Attribute directive accessing element and adding a listner

I need to write an attribute directive using Angular 1.5.5 which is basically restricting inputs on keypress event of the text box. So it should look like this
<input type="number" name="age" id="age" restrict-char="['e','-']" />
How can we write an attribute directive without using link function. I dont want to use link function since i will be porting my code base to Angular 2.0 and link functions are not supported there.
Not sure if that is what you want but you can use $parsers on ngModelController and set ng-model-options to update on any event.
angular.module('app', []);
angular.module('app').directive('restrictChar', () => {
return {
restrict: 'A',
require: 'ngModel',
scope: {
restricted: '=restrictChar'
},
controller: function ($scope, $element) {
const ngModel = $element.controller('ngModel');
ngModel.$parsers.unshift((value) => {
const newVal = value
.split('')
.filter((char) => $scope.restricted.indexOf(char) === -1)
.join('');
$element.val(newVal);
return newVal;
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>
<div ng-app="app">
<input type="text" ng-model="x" name="age" id="age" restrict-char="['e','-']" ng-model-options="{updateOn: 'keyup'}" /><br>
{{x}}
</div>

With AngularJS : Bind a radio button input to a Boolean with possible null value

Using AngularJS v1.5.0, I am trying to bind a radio input field to a Boolean variable that can be : true, false or null. Using the ng-value directive sets a null value to false.
<input type="radio" ng-model="foo.value" ng-value="true" ng-change="update()">
<input type="radio" ng-model="foo.value" ng-value="false" ng-change="update()">
<input type="radio" ng-model="foo.value" ng-value="null" ng-change="update()">
Would you have any idea about how this could be done ?
Thank you !
This works for me in 1.4.9. 1.5.0 and 1.6.3
<span ng-init="foo = {value: null}">{{foo}}</span>
<input type="radio" ng-model="foo.value" ng-value="null" ng-checked="foo.value === null" />Null
<input type="radio" ng-model="foo.value" ng-value="true" />True
<input type="radio" ng-model="foo.value" ng-value="false" />False
JsFiddle
If you look at the source code for the ngValue directive, you'll notice that it only runs scope.$eval() on values that are true, false or a number.
var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
var ngValueDirective = function() {
return {
restrict: 'A',
priority: 100,
compile: function(tpl, tplAttr) {
if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
return function ngValueConstantLink(scope, elm, attr) {
attr.$set('value', scope.$eval(attr.ngValue));
};
} else {
return function ngValueLink(scope, elm, attr) {
scope.$watch(attr.ngValue, function valueWatchAction(value) {
attr.$set('value', value);
});
};
}
}
};
};
To overcome this and include null in that group, you would need to write your own directive, or handle converting the value programmatically when the form gets submitted.

binding the model value of Twitter Bootstrap datepicker in controller in Angular js

I am building an application with Angular.js and Twitter Bootstrap.
HTML:
<div ng-controller="myController">
<label for="event">Event</label>
<input type="text" ng-model="event"/>
<label for="eventdate">Date</label>
<div class="input-append date" id="datepicker" data-date-format="dd-mm-yyyy">
<input class="span2" size="20" type="text" id="datepicker" ng-model="eventdate" required>
<span class="add-on"><i class="icon-th"></i></span>
<input class="btn-primary" type="submit" id="submit" value="Submit" ng-click="submit()" />
</div>
Controller:
var myApp1 = angular.module('myApp1', []);
myApp1.controller('myController', function($scope) {
$('#datepicker').datepicker();
$scope.submit = function () {
console.log($scope.event);
console.log($scope.eventdate);
};
});
When I click "Submit" button,
console.log($scope.event); prints the data entered in event text box.
But console.log($scope.eventdate); prints "undefined" when I select a date from the date picker
What may be the reason?
Please advice.
Your bootstrap datepicker is a 3rd-component outside of angular. When you change your date from the datepicker, angular is not aware of the changes.
You have to write a custom directive like this:
app.directive('datepicker', function() {
return {
restrict: 'A',
// Always use along with an ng-model
require: '?ngModel',
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return;
ngModel.$render = function() { //This will update the view with your model in case your model is changed by another code.
element.datepicker('update', ngModel.$viewValue || '');
};
element.datepicker().on("changeDate",function(event){
scope.$apply(function() {
ngModel.$setViewValue(event.date);//This will update the model property bound to your ng-model whenever the datepicker's date changes.
});
});
}
};
});
Apply the directive to html:
<div class="input-append date" datepicker ng-model="eventdate" data-date-format="dd-mm-yyyy">
<input class="span2" size="20" type="text" required="" />
<span class="add-on">
<i class="icon-th"></i>
</span>
</div>
DEMO

Angular JS update input field after change

I'm trying to build a simple calculator in Angular in which I can override the total if I want. I have this part working but when I then go back to enter in a number in fields one or two the total isn't updated in the field.
Here is my jsfiddle http://jsfiddle.net/YUza7/2/
The form
<div ng-app>
<h2>Calculate</h2>
<div ng-controller="TodoCtrl">
<form>
<li>Number 1: <input type="text" ng-model="one">
<li>Number 2: <input type="text" ng-model="two">
<li>Total <input type="text" value="{{total()}}">
{{total()}}
</form>
</div>
</div>
The javascript
function TodoCtrl($scope) {
$scope.total = function(){
return $scope.one * $scope.two;
};
}
You can add ng-change directive to input fields. Have a look at the docs example.
I'm guessing that when you enter a value into the totals field that value expression somehow gets overwritten.
However, you can take an alternative approach: Create a field for the total value and when either one or two changes update that field.
<li>Total <input type="text" ng-model="total">{{total}}</li>
And change the javascript:
function TodoCtrl($scope) {
$scope.$watch('one * two', function (value) {
$scope.total = value;
});
}
Example fiddle here.
I wrote a directive you can use to bind an ng-model to any expression you want. Whenever the expression changes the model is set to the new value.
module.directive('boundModel', function() {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ngModel) {
var boundModel$watcher = scope.$watch(attrs.boundModel, function(newValue, oldValue) {
if(newValue != oldValue) {
ngModel.$setViewValue(newValue);
ngModel.$render();
}
});
// When $destroy is fired stop watching the change.
// If you don't, and you come back on your state
// you'll have two watcher watching the same properties
scope.$on('$destroy', function() {
boundModel$watcher();
});
}
});
You can use it in your templates like this:
<li>Total<input type="text" ng-model="total" bound-model="one * two"></li>
You just need to correct the format of your html
<form>
<li>Number 1: <input type="text" ng-model="one"/> </li>
<li>Number 2: <input type="text" ng-model="two"/> </li>
<li>Total <input type="text" value="{{total()}}"/> </li>
{{total()}}
</form>
http://jsfiddle.net/YUza7/105/
Create a directive and put a watch on it.
app.directive("myApp", function(){
link:function(scope){
function:getTotal(){
..do your maths here
}
scope.$watch('one', getTotals());
scope.$watch('two', getTotals());
}
})

Resources