AngularJS - Auto $pristine and $error styles for form fields - angularjs

Can a simple directive be used to apply styles to form fields when they are $error and !$pristine?
For example, instead of writing a lengthy:
<div
ng-class="{'has-error':(myform.myField.$error && !myform.myField.$pristine) === true}">
<!-- myField is inside the div -->
Can I just write something like:
<div err-pris-cls="'has-error', myField">
Are directives the answer for this?

Rather than creating a new directive which will basically add class or remove it, I'd use ng-class directive itself, but will move code from html to controller which will also make sense to have testable code. That isValid controller function can be easily testable.
Markup
<div ng-class="{'has-error': isValid(myform.myField)">
Code
$scope.isValid = function(field){
return (field.$error && !field.$pristine) === true;
}

Related

ng-keyup firing but not reading properly when used with an ng-if inside a directive template

I have a directive and it works fine in a way such that when I type something the search() scope function inside my directive fires and sets $scope.query with the input text.
here is the directive template
<div class="container">
<div class="system-filter-header">
<div class="no-gutter">
<div class="system-search-wrapper search-wrapper-width">
<i ng-click="search($evt)" class="fa fa-search"></i>
<input type="text" ng-keyup=search($evt) class="search pull-left suggesstions-styles"
ng-model="query" ng-attr-placeholder="Search...">
</div>
</div>
</div>
</div>
here is the scope function which gets triggered
$scope.search = function() {
console.log($scope.query.length)
}
But when I used an ng-if="true" in first line of template (true used for generalizing only, I want to do a different conditional check inside ng-if) such that,
<div class="container" ng-if="true">
still the search gets triggered but the console.log gives always 0 and it doesn't seem to update the $scope.query value as it stays as $scope.query = ''
throughout the typing.
EDIT
Here is a an example codepen with almost similar behaviour. The problem is with the searchBox directive and I have added ng-if=true to the template but searching doesn't work. When I remove the ng-if searching works fine.
Any reason for this?
Rule of thumb in AngularJS: your ng-model should always include a dot. Otherwise AngularJS directives that create child scopes (like ng-if or ng-repeat) will create a duplicate property on that child scope instead of the parent scope. Following the controllerAs convention completely mitigates this behavior.

Changing the CSS of a div in AngularJS directive

I have a problem I have created a directive which is doing ng-repeat on an array of objects
---Showing the value on gui------
Now I want that if I click on any div of this repeat that particular div's background color should change
I have tried something like this
link:function(scope,element,attributes){
$(element).on('click',function(e){
$(element).addClass('A');
$(element).removeClass('B');
})
}
You can use the ng-class directive to apply classes on specific occurences, in your case in combination with the ng-click:
<div ng-repeat="item in items"
ng-class="{A: item.clicked, B: !item.clicked}"
ng-click="item.clicked = !item.clicked">
<!-- .. content -->
</div>
See this jsfiddle for example
You can try something like this, but this will need more workaround.
<div ng-click=“changeBackground($event)”></div>
// In Controller
$scope.changeBackground = function(event){
event.target.style.background = “#000”;
}
It would be better if you can submit your code.

How to bind html in angularjs

I have scope variable.like
$scope.demo='<h1>This is test</h1>';
I can bind html using ng-bind-html like
<p ng-bind-html="demo"></p>
Its working fine but how can bind html inside {{ .. }}
You need to sanitize the html using $sce service, which needs ngSanitize module injected in your app.
Basically you need to allow html as trustAsHtml mehthod of $sce service.
Code
$scope.demo = $sce.trustAsHtml('<h1>This is test</h1>');
Better way
For making it more better you could create an custom filter and reuse that code
app.filter('trsustedhtml', function($sce) {
return $sce.trustAsHtml;
});
Markup
<p ng-bind-html="demo| trsustedhtml"></p>
ng-bind html only take the text, you have to remove the safe control
<p ng-bind-html-unsafe="demo"></p>

Angular JS use NG-Hide with function

I try to create an Angular JS function that is displaying or hiding a Div in case that a certain requirement is met.
I do have the problem now that the function is not properly called and both divs are either visible or not visible (In the test case div 1 should be shown and div 2 not).
testApp.controller('MyController', ['$scope','$http',
function ($scope,$http) {
$scope.checkValue = function(value){
if(value >= 1)
return true;
else
return false;
};
}]);
In the html file I try to hide the Divs using the following parameters
<div class="classa" ng-hide="requestsExisting({{profile.arrayA.length}})">
<div class="classb" ng-hide="requestsExisting({{profile.arrayB.length}})">
Is during the run time the {{profile.parameterA.length}}passed to the function or the actual value that is stored in this variables? (It's 1 for arrayA and 0 for ArrayB)
you don't need the "{{" sign.
just do
<div class="classa" ng-hide="requestsExisting(profile.arrayA.length)">
<div class="classb" ng-hide="requestsExisting(profile.arrayB.length)">
the double curly brace is to put the value of the object in the html
The double curly brace notation {{ }} to bind expressions to elements
is built-in Angular markup
I think that it should work just with this code
<div class="classa" ng-hide="requestsExisting(profile.arrayA.length)">
<div class="classb" ng-hide="requestsExisting(profile.arrayB.length)">
I think that you don't need to use {{}} inside the ng-hide directive

AngularJS: create element dynamically

How do I go about create an element in my controller? e.g. on a click event?
example controller:
function AddCtrl($scope){
$scope.add = function(){
// do stuff to create a new element?
}
}
example view:
<div ng-controller="AddCtrl">
<button ng-click="add()">Add</button>
// create <input type="text" ng-model="form.anotherField">
</div>
Any suggestions much appreciated.
AngularJS is intended to follow MVC - so the controller creating an element in the view doesn't agree with the MVC behavior. The controller should not know about the view.
It sounds as if you want to have a control appear based on some conditional logic. One approach would be to bind to the visibility of the element.
In Angular, your controllers should not be manipulating the DOM directly. Instead, you should describe the elements you need in your templates, and then control their display with directives, like ng-switch, ng-hide / ng-show, or ng-if, based on your model, ie, your data.
For example in your controller you might do something like:
$scope.showForm = false;
And then in your partial:
<div id="myForm" ng-show="showForm">
<!-- Form goes here -->
</div>
By switching $scope.showForm between true and false, you will see your myForm div appear and disappear.
This is a classical mistake coming from jQuery moving to Angular or any other MVC library. The way you should think is to let the view react to changes in the scope.
$scope.items = []
$scope.add = function(){
$scope.items.push({});
}
In the view:
<input type="text" ng-repeat="item in items" ng-model="item.property">
If you want to display an element based on some condition or after the click, use ng-switch: http://docs.angularjs.org/api/ng/directive/ngSwitch
If you want to add multiple elements, create a repeated list of items and add an item to your view-model on clicking the button:
$scope.yourlistofitems = [];
$scope.add = function() {
$scope.yourlistofitems.push("newitemid");
}
And in the HTML:
<input type="text" ng-repeat="item in yourlistofitems" ng-model="item.property">

Resources