Improving AngularJS view update with ngshow - javascript

Right now I have a view that uses ng-show to show a select DOM object when certain criteria are met and ng-show for a input DOM for all other cases. When I do this and switch between the two cases, input box takes longer to disappear than when the select appears. The delay is pretty noticeable so I want to improve it so that there's very little delay between the two DOM changes.
Is there any way to do this?
<div>
<input ng-show="field && (type == 'search' || fieldBucket[field].moreBuckets)"
type="text" ng-model="value">
<select class="facet-value"
ng-show="field && type == 'filter' && !fieldBucket[field].moreBuckets"
ng-model="value"
ng-options="fieldBucket[field].buckets">
</select>
</div>

I don't think it is anyway related to ng-show or hide it might depend on some data which you are expecting from server as response.
I have created a simple demo for you that in basic ng-show/hide there isn't any leg if their value is set at same time.
<!doctype html>
<html ng-app>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
</head>
<body>
<div class="wrapper" ng-app="test">
<div class="phone" ng-controller="TestCtrl" ng-init="type = 'search'">
search
filter
<div >
<input ng-show="type == 'search'"
type="text" ng-model="value">
<select class="facet-value"
ng-show="type == 'filter'"
ng-model="value"
ng-options="obj.name for obj in list">
</select>
</div>
</div>
</body>
<script type="text/javascript">
var app = angular.module('test', []);
function TestCtrl($scope) {
$scope.list = [{name : 'one'}, {name : 'two'}];
}
</script>
</html>

Related

Why is my angular script running an infinite loop?

What I am trying to do is check three boxes via event click upon page load with the use of for loop. What happens is it runs an infinite loop then the page hangs. Here is the code:
<!DOCTYPE html>
<html >
<head>
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
</head>
<body ng-app="ngToggle">
<div ng-controller="AppCtrl">
<input type="checkbox" ng-model="dean" ng-click="btnChange($event, values, 1)" id="check-1" name="one" class="here" >
<input type="checkbox" ng-model="armada" ng-click="btnChange($event, values, 2)" id="check-2" name="one" class="here" >
<input type="checkbox" ng-model="armada" ng-click="btnChange($event, values, 2)" id="check-3" name="one" class="here" >
<!--<p ng-repeat="btn in btns">-->
<!-- <input type="checkbox" ng-model="btn.bool" class="here" > {{ btn.value }}-->
<!--</p>-->
{{btn }}
{{values }}
</div>
<script type="text/javascript">
angular.module('ngToggle', [])
.controller('AppCtrl',['$scope', '$timeout', function($scope, $timeout){
$scope.btns = [{}, {}, {}];
$scope.values = [];
$scope.btnChange = function(event, model, val){
_this = angular.element(event.target);
x = _this.prop("checked");
if(x){
model.push(val);
}else{
index = model.indexOf(val);
model.splice(index, 1);
}
};
ids = [1, 2, 3];
$timeout(function() {
for(x=0;x<ids.length;x++){
angular.element("#check-"+ids[x]).trigger("click");
}
}, 1000);
}]);
</script>
</body>
</html>
Here is the plunker: http://plnkr.co/edit/7DpCvkKLlKhRc3YwFTq0?p=info
PS
If you comment or removed the angular.element trigger this will not occur. If someone can provide a code that will trigger the click events on the checkboxes via loop. THEN IT WILL BE GREAT
You can do it the Angular way by setting default values to your checkboxes:
As you use ng-model, in your controller, just set dean and armada to true.
UPDATE:
I've nevertheless debugged your JS. Here is a plunker of your function working. I've used y in the loop (x was already defined) and change a bit the condition of looping.
Anyway, I would recommend you to do with Angular... :-)

Checkboxes binding in AngualrJS

I have two checkboxes , one with Data Binding and other one is without Data Binding.As you can see in the code below.
<html ng-app="notesApp">
<head><title>Notes App</title></head>
<body ng-controller="MainCtrl as ctrl">
<div>
<h2>What are your favorite sports?</h2>
<div ng-repeat="sport in ctrl.sports">
<label ng-bind="sport.label"></label>
<div>
With Binding:
<input type="checkbox" data-ng-true-value="YES" data-ng-false-value="NO" >
</div>
<div>
Using ng-checked:
<input type="checkbox" data-ng-checked='sport.selected === "YES"'>
</div>
<div>
Current state : {{sport.selected}}
</div>
</div>
</div>
<script type="text/javascript" src="angular.js"></script>
<script type="text/javascript">
angular.module('notesApp',[])
.controller('MainCtrl',[function(){
var self = this;
self.sports = [
{label:'Basketball',selected: 'YES'},
{label:'Cricket',selected:'NO'},
{label:'Soccer',selected:'NO'},
{label:'Swimming',selected:'YES'}
];
}]);
</script>
</body>
</html>
When i click on the checkbox of 'with data binding', it should bind and reflect the value in current state label.But it is not happening.Why ?.Can someone help Please .
2 problems I found with your code:
You forgot ng-model
You should specify a constant for ng-true-value and ng-false-value, by specifying YES angular will look for a YES property on the scope, write 'YES' instead
Updated working plnkr:
http://plnkr.co/edit/rnYRUpIICC7HAKdKXf3i?p=preview
<html ng-app="notesApp">
<head>
<title>Notes App</title>
</head>
<body ng-controller="MainCtrl as ctrl">
<div>
<h2>What are your favorite sports?</h2>
<div ng-repeat="sport in ctrl.sports">
<label ng-bind="sport.label"></label>
<div>
With Binding:
<input type="checkbox" ng-model="sport.selected" data-ng-true-value="'YES'" data-ng-false-value="'NO'" />
</div>
<div>
Using ng-checked:
<input type="checkbox" data-ng-checked="sport.selected === 'YES'" />
</div>
<div>
Current state : {{sport.selected}}
</div>
</div>
</div>
<script src="https://code.angularjs.org/1.4.3/angular.js"></script>
<script type="text/javascript">
angular.module('notesApp',[])
.controller('MainCtrl',[function(){
var self = this;
self.sports = [
{label:'Basketball',selected: 'YES'},
{label:'Cricket',selected:'NO'},
{label:'Soccer',selected:'NO'},
{label:'Swimming',selected:'YES'}
];
}]);
</script>
</body>
</html>
EDIT: As #g00glen00b mentioned, before angular 1.3 ng-true-value accepted only constant values, so in case you're not using angular 1.3 or later you don't have to wrap YES in quotes.
The data-ng-true-value and data-ng-false-value are used when you're using the input[checkbox] directive, but they do require ngModel, as you can see in the docs (note that ng-model is not in square brackets).
Without providing the model, AngularJS has no way to know where to apply the true/false value to. Adding data-ng-model does seem to work, as you can see in the following fiddle.
<input type="checkbox" ng-model="sport.selected"
data-ng-true-value="YES"
data-ng-false-value="NO" />
Also, please note that when using AngularJS 1.3 or higher, the values of ng-true-value and ng-false-value should be an expression rather than a constant value. Which means that for AngularJS 1.3 and higher you'll have to replace it by ng-true-value="'YES'", for example:
<input type="checkbox" ng-model="sport.selected"
data-ng-true-value="'YES'"
data-ng-false-value="'NO'" />
You are not applying "data-ng-model" attribute to the the checkbox. Please replace your "With binding" check box code from below:
<input type="checkbox" data-ng-model="sport.selected" data-ng-true-value="YES" data-ng-false-value="NO" >

Unable to trigger function inside controller using AngularJS / jQuery when focussed on last element in ng-repeat

In my webpage, when the user focusses on the last <input>, I want a set of a <input> and a <select> added dynamically.
If I do it with ng-click on a <button>, it works fine but not with focus event on the last <input>.
var Note = function($scope){
$scope.items = [];
$scope.options = [{name: 'x'}, {name: 'y'}];
$scope.add = function () {
console.log('adding..');
$scope.items.push({
question: "",
questionPlaceholder: "foo",
});
//console.dir($scope.items);
};
$scope.add();
$('input:last-child').on('focus', function(){ // does not work
console.log('adding elements dynamically');
$scope.add();
$scope.$apply();
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.min.js"></script>
<div ng-app>
<div ng-controller="Note" id='itemsPool'>
<form ng-submit="submitHandler()">
<div ng-repeat="item in items">
<input type="text" placeholder="URL" ng-model="item.question">
<select ng-init="item.type = options[0]"
ng-model='item.type'
ng-options="option.name for option in options">
</select>
</div>
</form>
<button ng-click='add()'>Add</button> <!-- works! -->
<span><-- button will be removed eventually</span>
</div>
</div>
How do I fix this?
Is it possible to fix this without using jQuery? How?
Don't use jQuery like you are using now, use dedicated Angular directives. In your case you need ngFocus.
This attribute will work well for you:
ng-focus="$last && add()"
Check the demo:
var Note = function($scope){
$scope.items = [];
$scope.options = [{name: 'x'}, {name: 'y'}];
$scope.add = function () {
console.log('adding..');
$scope.items.push({
question: "",
questionPlaceholder: "foo",
});
//console.dir($scope.items);
};
$scope.add();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.min.js"></script>
<div ng-app>
<div ng-controller="Note" id='itemsPool'>
<form ng-submit="submitHandler()">
<div ng-repeat="item in items">
<input type="text"
placeholder="URL"
ng-model="item.question"
ng-focus="$last && add()">
<select ng-init="item.type = options[0]"
ng-model='item.type'
ng-options="option.name for option in options">
</select>
</div>
</form>
<button ng-click='add()'>Add</button> <!-- works! -->
<span><-- button will be removed eventually</span>
</div>
</div>
The problem with your original approach is that there is nothing to bind focus event to, when you are using jQuery in controller, because ngRepeat has not yet rendered anything. Of course, you could workaround it easily with delegated event on the parent container, but you see how clumsy it is getting and not clear.

How select a check box on loading a page using angular

I have number of check boxes in my single page
<div class="check-outer">
<label>Place of operation</label>
<div class="checkDiv">
<div ng-repeat="place in places">
<div class="checkbox-wrapper">
<label>
<input type="checkbox" ng-model="placesOBJ[place.place_id]">
<span></span>
</label>
</div>
<label class="chk-lbl">{{place.place_name}}</label>
</div>
</div>
</div>
This is working perfectly. If data is present then i want to defaultly check this check boxes
if($scope.client.client_places){
var plcLength = $scope.client.client_places.length;
var client_places = new Array();
for(var i = 0; i < plcLength; i++){
client_places[i] = $scope.client.client_places[i]['place_id'];
}
// console.log(client_places);
//$scope.placesOBJ4 = client_places;
$scope.placesOBJ = client_places;
}
client places contain an array like {1, 2}
But this is not working. if any one know about this please help me.
You can use a directive ng-checked and pass in an expression based on the model
You can use ng-checkedto achieve what you need
<input type="checkbox" ng-model="placesOBJ[place.place_id]" ng-checked="placesOBJ">
If $scope.placesOBJ is populated (not null) then the expression is true and the checkbox will be selected
Just have a look at this simple code It will be useful for you
<body ng-app="myApp" ng-controller="HomeCtrl" ng-init="init()">
<div>
<label>Place of operation</label>
<div ng-repeat="place in places" ng-show="check">
<input type="checkbox" ng-model="placesOBJ[place.id]" ng-checked="true">
<label class="chk-lbl">{{place.name}}</label>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script>
var app=angular.module('myApp', []);
app.controller('HomeCtrl', ['$scope', function($scope) {
$scope.check=false;
$scope.places=[{'id':1, 'name':'place1'},{'id':2, 'name':'place2'},{'id':3, 'name':'place3'},{'id':4, 'name':'place4'}];
$scope.init=function()
{
if($scope.places)
{
$scope.check=true;
}
}
}]);
</script>
</body>
Explanation:- You can make use of ng-init="init()" to call on page load , it will check if data is present or not. If present then set ng-show="true" else by default it will be false

Clone elements in angularjs

I need to duplicate some input fields in order to handle data from clients. I have done it with jQuery http://jsfiddle.net/m7R3f/1/
HTML:
<fieldset id="fields-list">
<div class="pure-g entry">
<div class="pure-u-1-5">
<input type="text" class="pure-input-1" id="input-1" name="input-1">
</div>
<div class="pure-u-1-5">
<input type="text" class="pure-input-1" id="date" name="date">
</div>
<div class="pure-u-1-5">
<input type="text" class="pure-input-1" id="input-2" name="input-2">
</div>
</fieldset>
<button id="add">Add</button>
JS
$(document).ready(function ()
{
$("#add").click(function ()
{
$(".entry:first").clone(false).appendTo("#fields-list");
});
});
However I just start learning Angular and want to convert these code to Angular.
I have read questions in stackoverflow and found the code with angularjs here: http://jsfiddle.net/roychoo/ADukg/1042/. However, it seem works only for ONE input field? Can I clone/duplicate several input fields using AngularJS? (in other word: convert my code above into AngularJS version?)
Thank you very much.
If you want to clone html element, the best way to use ng-repeat directive.
Your Controller
var App = angular.module('App', []).controller('Test', ['$scope',
function($scope) {
$scope.inputCounter = 0;
$scope.inputs = [{
id: 'input'
}];
$scope.add = function() {
$scope.inputTemplate = {
id: 'input-' + $scope.inputCounter,
name: ''
};
$scope.inputCounter += 1;
$scope.inputs.push($scope.inputTemplate);
};
}
])
<!DOCTYPE html>
<html ng-app="App">
<head lang="en">
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-controller="Test">
<fieldset id="fields-list">
<div class="pure-g entry" ng-repeat="input in inputs track by input['id']">
<div class="pure-u-1-5">
<input type="text" class="pure-input-1" id="input" name="input-1">
</div>
<div class="pure-u-1-5">
<input type="text" class="pure-input-1" id="date" name="date">
</div>
<div class="pure-u-1-5">
<input type="text" class="pure-input-1" id="input-2" name="input-2">
</div>
</div>
</fieldset>
<button type="button" id="add" ng-click="add()">Add</button>
</body>
</html>
Angular prevents of creation duplicated elements, to avoid this, use track by like in the example
You should create an array and use ng-repeat in your HTML. Each object in the array can contain the data necessary to populate your divs. If you want to start with three entries, then add the data for those three. If you want to add more, then simply push onto the array. Because of Angular's 2-way data binding your form field will appear once the element is pushed onto the array.
For more details on how to do this, checkout the To Do example on Angular's home page.
How about this(Fiddle)
add two more ng-model and push those models
$scope.add = function(){
$scope.items.push($scope.newitem1,$scope.newitem2,$scope.newitem3);
}

Categories

Resources