NG-Repeat with NG-show Not executing with dynamic data - angularjs

Im trying to get a client list and detail view to work but i cant seem to figure it out. The NG-init wont work nor will the ng-click, I can get it to work if its hard coded, but when dynamically loading data it wont work. Id appreciate if anyone can point out the correct way to execute this.
html:
<div ng-controller="ClientCtrl as clients">
<table class="listview">
<tbody>
<tr ng-repeat="stuff in clients.records">
<td><a ng-click="client = {{$index}}" class="client-link">{{stuff.first_name}} {{stuff.last_name}}</a></td>
</tr>
</tbody>
</table>
<div class="detailview">
<div ng-repeat-start="things in clients.records " ng-if="$first">
<div id="contact-{{$index}}" class="tab-pane active" ng-show="client == {{$index}}" ng-init="client = {{$index}}">
<h2>{{things.first_name}} {{things.last_name}}</h2>
</div>
</div>
<div ng-repeat-end="things in clients.records " ng-if="!$first">
<div id="contact-{{$index}}" class="tab-pane active" ng-show="client == {{$index}}" ng-init="client = {{$index}}">
<h2>{{things.first_name}} {{things.last_name}}</h2>
</div>
</div>
</div>
</div>
controller.js:
function ClientCtrl($scope,$http,$interval, $rootScope){
var ClientCtrlData = this;
$http.get("api/clients").success(function(response) {
ClientCtrlData.records = response.records;
});
var promise;
// simulated items array
$scope.items = [];
// starts the interval
$scope.start = function() {
// stops any running interval to avoid two intervals running at the same time
$scope.stop();
// store the interval promise
promise = $interval(
function(){
$http.get("api/clients").success(function(response) {
ClientCtrlData.records = response.records;
console.log("People loaded");
});
}.bind(this)
,1000000 * 10);
};
// stops the interval
$scope.stop = function() {
$interval.cancel(promise);
};
// starting the interval by default
$scope.start();
$scope.$on('$destroy', function() {
$scope.stop();
});
}
angular
.module('inspinia')
.controller('ClientCtrl',ClientCtrl)
plnkr http://plnkr.co/edit/yzN787uL6C82Z6g6JNOq

First off, no need to use ng-click="client = {{$index}}", you're already saying that the code should be parsed by angular so no need for the angular brackets {{ }}.
Second, you need to scope client inside ng-click="client = $index" for example as such ng-click="clients.client = $index", otherwise angular doesn't know where to look for the property.
I also wonder what the need for the ng-init is? I'm guessing this is just mock functionality, because now it will just set the clients.client variable for each item until it ends up being the last one in the list.
In any case, here's a version of your code with fixed syntax, you should be able to take it from here
http://plnkr.co/edit/UyKYvxpErcehizSBKaqy?p=preview
<div ng-controller="ClientCtrl as clients">
<table class="listview">
<tbody>
<tr ng-repeat="stuff in clients.records">
<td>
<a ng-click="clients.client = $index" class="client-link">{{stuff.first_name}} {{stuff.last_name}}</a>
</td>
</tr>
</tbody>
</table>
<div class="detailview">
<div ng-repeat="things in clients.records ">
<div id="contact-{{$index}}" class="tab-pane active" ng-show="clients.client == $index" ng-init="clients.client = $index">
<h2>{{things.first_name}} {{things.last_name}}</h2>
</div>
</div>
</div>
</div>

Related

How to limit results with ng-repeat?

Sorry for the basic question, extremely new to software development and angular in particular. I'm currently making a small app that uses an api to find cinemas near a certain postcode.
I have made a results page that show what films are playing in a certain cinema, but I want to limit the amount of results returned and include a 'Show more films' button.
I have included my html and controller below:
HTML
<div class="main-container">
<fountain-header></fountain-header>
<div class="cinemas-container">
<h2 align="center" class="cinemas-h2">Movies playing here:</h2>
<div class="cinema2" ng-repeat="listing in $ctrl.listings">
<h3 class="cinema-h5">{{listing.title}}</h3>
<ul class="cinema-h4">
<li ng-repeat="time in listing.times">{{time}}</li>
</ul>
</div>
<div class="main-container">
</main>
</div>
<fountain-footer></fountain-footer>
</div>
</div>
ListingsController
function ListingsController($http, $stateParams) {
console.log($stateParams);
console.log($stateParams.cinemaID);
var vm = this;
$http
.get('https://api.cinelist.co.uk/get/times/cinema/' + $stateParams.CinemaID +'?day=1')
.then(function (response) {
console.log(response);
vm.listings = response.data.listings;
});
}
Could I just use limitTo to achieve this?
P.S sorry for the poor information, it's my first question on here.
Please try the following example in the fiddle link -
Using the limitTo filter.
ng-repeat="d in data | limitTo: limitvar"
https://jsfiddle.net/m0q9ju8a/
let me know if this helps.
You can do like this:
HTML
<div class="main-container">
<fountain-header></fountain-header>
<div class="cinemas-container">
<h2 align="center" class="cinemas-h2">Movies playing here:</h2>
<div class="cinema2" ng-repeat="listing in vm.listings | limitTo: vm.limit as results">
<h3 class="cinema-h5">{{listing.title}}</h3>
<ul class="cinema-h4">
<li ng-repeat="time in vm.listing.times">{{time}}</li>
</ul>
</div>
<button ng-hide="results.length === vm.listings.length" ng-click="vm.limit = vm.limit +8">show more...</button>
<div class="main-container">
</main>
</div>
<fountain-footer></fountain-footer>
</div>
</div>
and in youn controller
function ListingsController($http, $stateParams) {
console.log($stateParams);
console.log($stateParams.cinemaID);
var vm = this;
vm.limit = 8;
$http
.get('https://api.cinelist.co.uk/get/times/cinema/' + $stateParams.CinemaID +'?day=1')
.then(function (response) {
console.log(response);
vm.listings = response.data.listings;
});
}

how to bind $index from ng-repeat to controller

In Angular I wanted to bind $index to controller. How can I send $index value in to my controller. Here is my html code.
<body>
<div class="container">
<div class="row row-content" ng-controller="demoController as demoCtrl">
<ul>
<li ng-repeat="val in demoCtrl.list" >Hello {{$index}}</li>
</ul>
</div>
</div>
Here is my controller code
var app = angular.module('confusionApp',[])
app.controller('demoController', function(){
var list = [1,2,3,4,5];
this.list = list;
var array = ['abc','def','ghi','jkl','mno']
this.array = array
console.log(this.array[index]);
});
I need to use ng-modal in HTML and bind that value to some variable in my controller.
Based on the selection of index, it should check in array and respective array should have to print.
Can any of you please help
To get your current iteration position in your controller you have define a function.
So your html code like this.
<body>
<div class="container">
<div class="row row-content" ng-controller="demoController as demoCtrl">
<ul>
<li ng-repeat="val in demoCtrl.list" ng-click="dispArray($index)">Hello {{$index}}</li>
</ul>
</div>
</div>
And your controller code
var app = angular.module('confusionApp',[])
app.controller('demoController', function($scope){
$scope.dispArray = function(index){
// console.log(index);
// your code
}
});
Depending on what you're trying to accomplish you might be better served creating a custom iterator.
function makeIterator(array){
var nextIndex = 0;
return {
next: function(){
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true};
}
}
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators
Angular is going to iterate over everything in the list when you use ngRepeat. If you're trying to track which list item a user clicks then you'll just add that in there using $index.
<li ng-repeat="val in demoCtrl.list" >
<span ng-click="demoCtrl.userClicked($index)"> Hello {{$index}}</span>
</li>
If you're just trying to print the data in each item, ng-repeat is already iterating everything for you.
<li ng-repeat="val in demoCtrl.list" >
<span ng-click="demoCtrl.userClicked($index)"> Hello {{val}}</span>
</li>
It all depends on what you're trying to do.
i dont konw what u want to do. if u want to use event. you can pass $index to your controller function like:
<li ng-repeat="val in demoCtrl.list" ng-click="getIndex($index)">Hello {{$index}}
$scope.getIndex = function($index) {
console.log($index)
}
hope to help u.

Workaround for error 10 $digest() iterations reached

I am displaying data from the database (using Web API) on the page:
<div ng-repeat="Item in Items">
<div class="row">
<div class="col-sm-3">{{Item.Id}}</div>
<div class="col-sm-3">{{Item.Desc)}}</div>
<div class="col-sm-6">{{Item.CollectionID}}</div>
</div>
</div>
the above works fine, but when I try getting actual Collection Name, I get an issue:
<div ng-repeat="Item in Items">
<div class="row">
<div class="col-sm-3">{{Item.Id}}</div>
<div class="col-sm-3">{{Item.Desc)}}</div>
<div class="col-sm-6">{{GetCollectionName(Item.CollectionID)}}</div>
</div>
</div>
here is my controller function for getting Collection Name:
$scope.GetCollectionName = function (CollId) {
$http.get('http://Server/App/api/GetCollName/' + CollId).
then(function (result) {
$scope.CollectionName = result.data;
return $scope.CollectionName;
});
}
is there a better way to do this besides modifying my underlying query?
The basic idea here is to use ng-init to initialize a local CollectionName variable for each Item in your ng-repeat. You can then use that local variable to output CollectionName[Item.CollectionID].
Here's a working demo
<div ng-repeat="Item in Items" ng-init="GetCollectionName(Item.CollectionID)">
<div class="row">
<div class="col-sm-3">{{Item.Id}}</div>
<div class="col-sm-3">{{Item.Desc)}}</div>
<div class="col-sm-6">{{CollectionName[Item.CollectionID]}}</div>
</div>
</div>
$scope.CollectionName = [];
$scope.GetCollectionName = function (CollId) {
$http.get('http://Server/App/api/GetCollName/' + CollId)
.then(function (result) {
$scope.CollectionName[CollId] = result.data;
});
}
It is bad practice to call the function inside loop. And you are using expression tag in angularjs which creates watcher. Always make sure all the necessary records to display is already in the associated scope variable.
$scope.GetCollectionName = function (CollId) {
if(!$scope.someDataCheck[CollId] && !$scope.someData[CollId]){
$scope.someDataCheck[CollId] = true;
$http.get('http://Server/App/api/GetCollName/' + CollId).
then(function (result) {
$scope.someDataCheck[CollId] = false;
$scope.someData[CollId].data = result.data;
});
}
return $scope.someData[CollId];
}

Nested ng-repeat with different data

I am using AngularJS v1.5.0 in my web application. I have feedbacks of the users which are displayed using ng-repeat. Now whenever the executive clicks on the feedback, I make a server call and fetch the history of user and show it on the panel.
Once the call is successful, I assign the data to the feebackDetails variable which is now the controller scope variable. But I dont want it to have the controller scope, as each feedback will have different user and different data.
<div class="tab-pane fade in" ng-controller="controller-feedback" id="feedback">
<div class="col-md-12">
<div class="row">
<div ng-repeat="feedback in feedbacks track by $index" ng-click="getUserHistory(feedback.userId)" data-toggle="collapse" data-target="#feedback{{$index}}" aria-expanded="false" aria-controls="#feedback{{$index}}">
<div class="alert alert-info">
<div>{{feedback.feedback}}</div>
<div class="collapse" id="feedback{{$index}}">
<div class="well">
<div ng-repeat="feedbackDetail in feedbackDetails track by $index">
<span style="font-weight: bold">Question:</span> {{feedbackDetail.question}} <br>
<span style="font-weight: bold">Answer:</span> {{feedbackDetail.answer}} <br>
<span style="font-weight: bold">Helpful:</span> {{feedbackDetail.helpful}} <br>
<span style="font-weight: bold">Feedback:</span> {{feedbackDetail.feedback}} <br>
<span style="font-weight: bold">Executive:</span> {{feedbackDetail.executive}} <br>
<hr ng-hide="$last">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
This is my controller part.
app.controller('controller-feedback', function ($scope, $http, $rootScope) {
$scope.feedbacks = [];
$scope.feedbackDetails = [];
// This will get the feedbacks
$http
.get(phpUrl + 'test-feedback', {params:{doctorId:doctorId}})
.then(function success(response) {
$scope.feedbacks = response.data.data;
$rootScope.feedbackCount = response.data.data.length.toString();
}, function error(success) {
});
$scope.getUserHistory = function(userId) {
console.log(userId);
$http
.get(phpUrl + 'test-feedback-details', {params:{userId:userId}})
.then(function success(response) {
/**
* This variable $scope.feedbackDetails must be different for each ng-repeat
*/
$scope.feedbackDetails = response.data;
}, function error(success) {
});
};
});
change getUserHistory to accept feedback object.
$scope.getUserHistory = function(feedback) {
var userId = feedback. userId ....
and rather than
$scope.feedbackDetails = response.data;
assign
$scope.feedback.feedbackDetails = response.data;
Inner ng-repeat should use feedback.feedbackDetails.
You could create a directive called feedbackDetail that you put inside your ng-repeat which uses an isolate-scope and you pass in your feedbackDetail from the ng-repeat.
Then when you make the HTTP request from the directives controller and assign it to $scope it would be a scope for just that part of the repeat.

how to access data from scope object

I need to get data from $scope.List2 object:
<div ng-app="App">
<div id="firstlist" ng-controller="Controller">
<table id="requesttable" class="RequestTable">
<tr ng-repeat="item2 in List2">
<td class="selectedItem">{{item2.Title}}</td>
</tr>
</table>
<button id="Reqbutton" onclick="SendRequest()">Send</button>
</div>
</div>
The problem is that if I put SendRequest function inside controller then it cannot be called (I get "SendRequest() is not defined" message). And if I put the function outside the controller I cannot access List2.
What do I miss?
As #sp00m suggested. You should use ng-click instead of onclick on the button. The html would look like this then:
<button id="Reqbutton" ng-click="sendRequest()">Send</button>
In your controller
app.controller('testController', ['$scope', function {
$scope.list2 = [];
$scope.sendRequest = function() {
var test = $scope.list2;
...
};
}]);

Resources