why is my list not rendering? - javascript

by default it shows 10 elements, but when i change the input it does not update, below is the code and fiddle.
JS Code:
var app = angular.module('myapp',[]);
app.controller('ctrlParent',function($scope){
$scope.listItems = 10;
$scope.newTotal = function(){
$scope.$apply(function(){$scope.lisItemsTotal})
}
$scope.lisItemsTotal = function(num) {
return new Array($scope.listItems);
}
});
http://jsfiddle.net/0dwmqn8y/1/

The reason is that after changing the input $scope.listItems is a string, as the input type is text. Change it to number and all will work. Working plunker: http://jsfiddle.net/yv0z9q8L/
<input type="number" name="red" ng-model="listItems" onchange="angular.element(this).scope().newTotal()">
Also note, that you don't need onchange attribute at all here, however I am unsure whether this is a good thing. Using a function in for ng-repeat is quite dangerous unless you know what you are doing, as this function will be called in each digest cycle. If you are planning to loop over large set of data, it will pretty much kill your performance.
Personally, I would rather go with:
<div ng-app="myapp">
<div ng-controller="ctrlParent">
<input type="number" name="red" ng-model="itemCount">
<ul>
<li ng-repeat="i in items track by $index"><span>{{$index+1}}</span></li>
</ul>
</div>
</div>
var app = angular.module('myapp',[]);
app.controller('ctrlParent',function($scope){
$scope.$watch('itemCount', function(val) {
$scope.items = Array.new(val)
});
$scope.itemCount = 10;
});
plunker: http://jsfiddle.net/m1zq3zqv/1/

The data, that you get from the input field is a string, so you can either change the input type to number or apply a bit of parsing in your code by changing the following line
return new Array($scope.listItems);
to this:
return new Array(parseInt($scope.listItems));

Related

Angular.js - Slicing a json request according to user input

I am a beginner at Angular.js and am currently going through the tutorial. I decided to try making the number of phones displayed changeable by the user. In my controller:
function PhoneListController($http) {
var self = this;
self.orderProp = 'age';
$http.get('phones/phones.json').then(function(response) {
self.phones = response.data.slice(0, self.displayNum);
});
}
PhoneListController.$inject = ['$http']; //services to inject for each parameter in PhoneListController
I slice the response data that I get from the server according to the displayNum input by the user. I'm sure that displayNum is updated in the model, however it doesn't slice the json as I expected it to. Is the http request only made once at the start?
The relevant section of my template:
<p>
Number of phones displayed:
<input ng-model="$ctrl.displayNum" />
</p>
...
<ul class="phones">
<li ng-repeat="phone in $ctrl.phones | filter:$ctrl.query | orderBy:$ctrl.orderProp">
<span>{{phone.name}}</span>
<p>{{phone.snippet}}</p>
</li>
</ul>
<p>display num: {{$ctrl.displayNum}}</p>
The display num: {{$ctrl.displayNum}} at bottom updates according to the number input in <input ng-model="$ctrl.displayNum" />, but the list does not change size. If I hardcode a value in for self.displayNum in the controller the list is sliced correctly when I refresh the page, but changing the value in the input does nothing to the list.
As mentioned by #Alexander-Bolzhatov, I simply put the http request in a change function, called by ng-change in the template.
$http.get('phones/phones.json').then(function(response) {
self.phones = response.data;
});
self.change = function(){
$http.get('phones/phones.json').then(function(response) {
self.phones = response.data.slice(0, self.displayNum);
});
};
Template code:
Number of phones displayed:
<input ng-model="$ctrl.displayNum" ng-change="$ctrl.change()"/>

Angular JS - ng-repeat repeating old values

I am new to Angular JS. I have created a code in angular using app and controller. What I am tyring to do is to add name dynamically to a array when a button is clicked.
By default my array has two value passed. When i give an input and click the add button,it adds the string for the first time.
But when i give another input and click add again, the old string is replaced by the new string and the new string is added again.
Here is the piece of code on JSFiddle: http://jsfiddle.net/5DMjt/3680/
var demo= angular.module("demo",[]);
var simplecontroller = function($scope){
$scope.members = [{id:1,name:'prateek'},{id:2,name:'Ruchi'}];
$scope.addmember = function(newmember){
newmember.id = $scope.members.length+1;
$scope.members.push(newmeber);
demo.controller(simplecontroller);
}
}
and here is the HTML Code:
<div ng-app="demo">
<div ng-controller="simplecontroller">
<ul>
<li ng-repeat="member in members">{{member.id}}-{{member.name}}</li>
</ul>
Name<input type="Text" ng-model="inputmember.name">
</br><h2>
{{inputmember}}
</h2>
<input type="button" value="Add" ng-click="addmember(inputmember)">
</div>
</div>
Please Help !
What i analyzed is that push function is passing the address that is why binding still exists.What u can do is pass the value instead like i did below-:
$scope.addmember = function(newmember){
newmember.id = $scope.members.length+1;
$scope.members.push({id:newmember.id,name:newmember.name});
demo.controller(simplecontroller);
}
Hope this solves your problem.Happy learning :)
You have two options.
Either you can reinitialize it every time what I would not recommend.
And the other one is to, pass the parameters with values.
$scope.members.push({id:newmember.id,name:newmember.name});
:)
See this updated fiddle: http://jsfiddle.net/5DMjt/3689/
Name<input type="Text" ng-model="newname">
This gives you a scope variable newname.
<input type="button" value="Add" ng-click="addmember()">
And addmember function uses this newname to create a new object and add it to the list:
$scope.addmember = function(){
var newmember = {};
newmember.id = $scope.members.length+1;
newmember.name = $scope.newname;
$scope.members.push(newmember);
}
You have a syntax error. See console error for more info.
Your variable inputmember is not defined anywhere.
Also you need to push to array new reference of the object, so the old one in array does not change each time you type value.
Here is a working version.
http://jsfiddle.net/a9zvgm8k/
$scope.addmember = function(newMember){
newMember.id = $scope.members.length+1;
$scope.members.push(angular.extend({}, newMember));
demo.controller(simplecontroller);
}
$scope.members = $scope.members.concat({id: newmember.id, name: newmember.name});
Solved : http://jsfiddle.net/5DMjt/3693/
Before pushing to $scope.members you need to create a new object and populate it with id and name from the input.

Angularjs - how to bind to an html element appended by javascript code

I want to bind angular event and model to an html element appended by javascript code.
My code is here. https://jsfiddle.net/hq7qk48n/13/
<div ng-app>
<div ng-controller="MyController">
<input type="text" ng-model="text1">
click1
<div id="append"></div>
<p ng-if="clickedTime1">click1 : {{ clickedTime1.toLocaleString() }}</p>
<p ng-if="clickedTime2">click2 : {{ clickedTime2.toLocaleString() }}</p>
<p>{{ text1 }}</p>
<p>{{ text2 }}</p>
</div>
</div>
function MyController($scope) {
$scope.clickedTime1 = null;
$scope.clickedTime2 = null;
$scope.onClick = function () {
var html = '<input type="text" ng-model="text2" name="text"> click2';
$("#append").empty();
$("#append").append(html);
$scope.clickedTime1 = new Date();
}
$scope.onClick2 = function () {
$scope.clickedTime2 = new Date();
};
}
onClick2() doesn't work. and model "text2" is not updated.
How to bind onClick2 function and text2 model?
Need to compile an html element? How?
This is a little tricky because you have an ng-click in your new element. There are 2 things we need to deal with.
Correctly add the element
Make your new element see the scope
First we will start with your call to the method from your element. You will need to add $event to the call
click1
The $event object will give you information about the calling element.
You also need to add it to your method
$scope.onClick=function($event){
Next, your element required use of the scope so we need to turn it into an element. Otherwise just html would be fine.
var el=angular.element('<input type="text" ng-model="text2" name="text"> <a href="#" ng-click="onClick2()"/>click2</a>');
Now you can use a little jquery but exactly on the target element the way angular would do it.
$($event.currentTarget).empty();
$($event.currentTarget).append(el);
At this point you would see your changes but the bindings will not work because it is not attached to the scope so we need to compile it. You will need to add the $compile server to your controller
function MyController($scope,$compile) {
Now we can use the service to compile the new element
$compile(el)($scope);
You should now see everything functioning the way you would expect
function MyController($scope,$compile) {
$scope.clickedTime1 = null;
$scope.clickedTime2 = null;
$scope.onClick = function ($event) {
var el = angular.element('<input type="text" ng-model="text2" name="text"> click2');
$($event.currentTarget).empty();
$($event.currentTarget).append(el);
$compile(el)($scope);
$scope.clickedTime1 = new Date();
}
$scope.onClick2 = function () {
$scope.clickedTime2 = new Date();
};
}
and don't forget to add the $event to your call as well.
I did not use your exact code but I tested this as I answered to verify and it worked perfectly. It might not be best practice to work with the DOM elements in your controller but sometimes it just works. That is how you do it.

Angularjs toggle between input and span values in a table row

I have following code in my html where I want to toggle input and span fields. In a table row.
<table>
<tbody ng-repeat="(i, cont) in char.items">
<tr>
<td>
<div>
<a ng-click="choose()">
<input type="text" ng-model="item.desc" ng-show="sho==1" />
<span ng-show="sho==0">{{item.type}}</span></a>
</div>
</td>
</tr>
</tbody>
</table>
<div ng-click="addRows(char)" style="WIDTH: 974px">Add Row</div>
In my controller I have
app.controller("testCtrl", function($scope) {
$scope.sho=0;
$scope.addRows = function(char) {
if (typeof char.items == 'undefined') {
char.items = [];
}
char.items.push({ des: '', type: '', price: '', charge__id: ''});
};
$scope.choose= function() {
//some values are retrieved than I want to toggle so it shows the
//want to set sho=1 so input is hidden instead the span vaue is shown
$scope.sho=1;
};
});
Problem is when I set $scope.sho=1; it shows span value in all the row of the table.
While I add a new row I just want to show the input box leaving the other rows already inserted with span values.
Pleae let me know how can i set ng-show for each row in table.
Thanks
Since ng-repeat creates a child scope for each item you can leverage that within a directive. The parent scope of the directive will be the child scope created by ng-repeat and therefore isolated from other repeaters
Move your choose and sho out of main controller and put them into directive scope.
<div editable>
<a ng-click="choose()"></a>
<input type="text" ng-model="item.desc" ng-show="!sho" />
<span ng-show="sho">{{item.type}}</span>
</div>
app.directive('editable', function () {
return function (scope, elem, attrs) {
scope.sho = true;
scope.choose = function () {
scope.sho = !scope.sho;
}
}
});
This is the simplest version possible without going to isolated scope within the directive and without considering factors like more than one of these editables in a row.
For more insulated feature rich version would consider using a more robust directive like x-editable
I have trouble understanding what your code is actually used for. But my guess would be for you to pass the current item into the choose function and set a flag on the item itself. If you modify your ng-show and ng-hide attributes to react to this flag on each item, I guess you would reach your goal.
<a ng-click="choose(item)">
<input type="text" ng-model="item.desc" ng-show="item.sho==1" />
<span ng-show="item.sho==0">{{item.type}}</span></a>
</div>
And in your choose function you would do something like this:
$scope.choose= function(item) {
item.sho=1;
};
This is only a wild guess though, since it isn't quite clear to me what you are trying to accomplish.
Two things that come to mind immediately are:
1 - Pass in the item with the function and have the function accept an argument.
<a ng-click="choose(sho)">
and then in your controller
$scope.choose= function(sho) {
sho = 1;
};
2 - Just make ng-click set the value to one..
<a ng-click="sho = 1">

How to programmatically select ng-option value?

I have a view that is filled with dropdownlists to filter a report. I also have a view of saved filters that are displayed as links. When a user clicks on their saved filters, I want the appropriate values of the dropdownlists to be selected. The drop downs are being populated properly. On the saved filter link there is an ng-click that will call a function that iterates through the collection of saved filter values and automatically selects the correct one. I cannot figure out how to programmatically set the selected option. Any help is much appreciated!
<select uid="locSelect"
class="span12"
ng-model="reportDetail.selectedLoc"
ng-options="loc.dbid as loc.serviceName for loc in reportDetail.locList | orderBy:'name'">
<option uid="unselectedLocOption" value="">-- Select One --</option>
</select>
Here is the list of saved filters:
<div class=" well fixed-search" style="overflow-x: hidden;overflow-y: auto;">
<div class="well-header">
Saved Filters
</div>
<div ng-if="!hasSavedFilters">
<span>No saved filters</span>
</div>
<ul ng-if="hasSavedFilters" class="nav nav-list dashboard-list">
<li ng-repeat="filter in reportDetail.savedFilters">
<a uid="savedFilter" href="" ng-click="reportDetail.loadSavedFilters(filter.filters)">
<span ng-bind="filter.title"></span>
</a>
</li>
</ul>
And here is my controller
(function(){
'use strict';
var ReportDetailController = function(ReportsService, $scope){
var _locList = {};
var _hospitalStatusList = {};
var _providerStatusList = {};
var _savedFilters = [];
var _sourceTypeList = {};
var _dateRangeList = {};
var _init = function(){
ReportsService.getCurrentReportSavedFilters().then(function(data){
$scope.reportDetail.savedFilters =data;
$scope.hasSavedFilters = ReportsService.hasSavedFilters();
});
ReportsService.getLOCListForDDL().then(function(data){
$scope.reportDetail.locList = data;
//$scope.reportDetail.selectedLoc = $scope.reportDetail.locList[0];
});
ReportsService.getSelectListData()
.then(function(data){
$scope.reportDetail.sourceTypeList = data.CONNECTION_TARGET_STATUS;
$scope.reportDetail.hospitalStatusList = data.CONNECTION_SOURCE_STATUS;
});
ReportsService.getDateRangesForDDL()
.then(function(data){
$scope.reportDetail.dateRangeList = data;
});
$scope.reportDetail.providerStatusList = ReportsService.getProviderStatusForDDL();
};
var _loadSavedFilters = function(filters){
for(var i = 0, l = $scope.reportDetail.locList.length; i<l; i++){
if($scope.reportDetail.locList[i].serviceName == filters.levelOfCare){
$scope.reportDetail.selectedLoc = $scope.reportDetail.locList[i];
console.log($scope.reportDetail.selectedLoc);
}
}
}
var _isActive = function(filter){
for(var i = 0, l = $scope.reportDetail.savedFilters.length; i<l; i++){
if(filter.title == $scope.reportDetail.savedFilters[i].title){
return true;
}
return false;
}
}
var _generateReport = function(){
return ReportsService.generateReport();
};
$scope.reportDetail = {
init: _init,
selectedLoc: null,
isActive: _isActive,
locList: _locList,
selectedHospitalStatus: 'NOTIFIED',
hospitalStatusList: _hospitalStatusList,
selectedProviderStatus: 'NEW',
providerStatusList: _providerStatusList,
selectedSourceType: 'CONNECTED',
sourceTypeList: _sourceTypeList,
selectedDateRange: '',
dateRangeList: _dateRangeList,
savedFilters: _savedFilters,
loadSavedFilters: _loadSavedFilters,
generateReport: _generateReport
};
$scope.reportDetail.init();
};
app.controller('ReportDetailController', ['ReportsService', '$scope', ReportDetailController]);
})();
You just need to set the ng-model to whatever it should be, so in this case you would set reportDetail.selectedLoc to whatever loc.dbid it should be.
For example: http://jsfiddle.net/uWLua/1/
Note: Make sure they have the same type, so in your example make sure they are either both integers, or both strings, it will not know they are the same if you have one as 5073 and one as "5073"
I updated the fiddle to show that the string and number do not do the same thing.
The ng-model and the expression feeding ng-options -must- match in order for Angular to compare values and see what option is 'selected'. Just as 'dave' indicated.
Due to time constraints I ended up going a different route. I created an event bus of sorts in my service layer and subscribe to the even in my controller, updating the model, and used ng-repeat with ng-selected.
I'm still interested to understand why this was not working with ng-options. The model and ng-options types matched, and everything appeared to be wired up correctly. When I have more time i'll re-address the original issue. Thanks for all who responded!
You need custom directive, or something similar to this two approaches
<div ng-controller="MyCtrl">
<h1>Approach 1</h1>
<span ng-repeat="val in dbs">
<input type="checkbox" ng-model="val.checked">{{val.name}}
</span>
<hr/>
<h1>Approach 1</h1>
<select multiple>
<option ng-repeat="val in dbs" name="val.name" value="val.name" ng-selected="val.checked">{{val.name}}</option>
</select>
<h4>Source (note scope changes)</h4>
{{dbs}}
</div>
also you can use ng-change to do some complex ops
If I understand, in summary, you have a select filled with a list, and you want to programmatically set one of those to be selected, type it as the default right?
If so, you can easily solve this with ng-options, just associate your controller instance with scope and assign the position of the list you want to the model of select, for example:
Select HTML
<select ng-model="vm.aluno_id" name="aluno_id" ng-options="aluno.nome for aluno in alunos">
Controller
app.controller("auxiliarController", function( $scope){
//instancia controller;(Controller instance;)
var vm = this;
$scope.vm = vm;
//carregando lista no scope, que serĂ¡ utilizado pelo angular no select
//Loading list in scope, which will be used by angular in select
$scope.alunos = [{id: 1, nome: "aa"}, {id: 2, nome: "bb"}];
//setando item default no select
$scope.vm.aluno_id = $scope.alunos[0];
});
I hope I have helped

Categories