Extending ngRepeat array without digest the whole array - arrays

When you have an expandable array, what would be the most sufficient way to extend array, without digesting the whole array over.
[].push.apply(scope.table, extending);
.filter('to_trusted', ['$sce', function ($sce) {
return function (text) {
return $sce.trustAsHtml(text);
};
}])
<tbody>
<tr ng-repeat="row in table track by row.index"
once-class="row.theme"
ng-bind-html="table[row.index].tpl | to_trusted">
</tr>
</tbody>

Related

Delay in ng-repeat

How can I insert delay between every ng-repeat iterations so my table will generate records slower. Is there any way to do it without using ngAnimate.
<table>
<tr ng-repeat="x in records">
<td>{{x}}</td>
</tr>
</table>
[Suggestion]
If you data is loading slow, maybe is because you have duped keys, so for test it you can try with track by $index like this
<table>
<tr ng-repeat="x in records track by $index">
<td>{{x}}</td>
</tr>
</table>
[Solution ]
If you still want to control the interaction of ng-repeat, it is best to create a dynamic variable that is manipulated as time passes, then you can have a primary array with all records
$scope.records = [
{
"name": "name1",
"data2": "data2.1",
"data3": "data3.1"
},
{
"name": "name2",
"data2": "data2.2",
"data3": "data3.2"
},
{
"name": "name3",
"data2": "data3.3",
"data3": "data3.3"
}
];
Then you could use setTimeout to call a function that passes data from the primary array to another final array, an index per interaction
//start to proccess
setTimeout(function(){$scope.Result();},1000);
//Here pass data from Records to FinalResult in each interaction
$scope.Result=function(){
dif=$scope.records.length-$scope.FinalResult.length;
currentRow=$scope.FinalResult.length;
if(dif>0){
$scope.FinalResult.push($scope.records[currentRow]);
}
if($scope.records.length>$scope.FinalResult.length){
setTimeout(function(){$scope.Result();},1000);
}else{
console.log('Finish Load');
$scope.FinishRender=true;
}
//refresh
$scope.$apply();
}
And finally deliver this variable with another function...
//get the finish Array
$scope.getFinalResult=function(){
return $scope.FinalResult;
}
and HTML
<body>
<div ng-controller="recordsCtrl">
<table style="border:1px solid black">
<tr ng-repeat="x in getFinalResult()">
<td>{{x.name}}</td>
<td>{{x.data2}}</td>
<td>{{x.data3}}</td>
</tr>
</table>
<div ng-if="FinishRender" style="color:red;font-weight:bold">Data Loaded!!!</div>
</div>
</body>
Please feel free to check a solution in punkler
[Optional]
Also you could use a directive to control the last interaction like this
myApp.directive('onFinishRender', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
console.log(element);
if (scope.$last === true) {
console.log('Finish Load');
}
}
}
});
and html
<table>
<tr ng-repeat="x in getFinalResult()" on-finish-render="onFinishRender">
....
...
</tr>
</table>
note:I'm not really sure but I think it's possible to capture every interaction with this method
A possible solution in your situation could be to take the source array and populate the ng-repeat array in increments with a delay using _.chunk and $timeout, as such:
index.html
<table>
<tr ng-repeat="x in records track by $index">
<td>{{x}}</td>
</tr>
</table>
appCtrl.js
$scope.sourceData = [data, data, data];
$scope.records = [];
/**
*#param source (array): the array with the data used to populate the ng-repeat array
*#param target (array): the array to which ng-repeat points
*#param delay (integer): the render delay, in milliseconds
*#param renderSize (integer): the amount of list items to render between each delay
*
**/
function delayedRender(source, target, delay, renderSize) {
var promise = $q.resolve();
function scheduleRender(partial) {
Array.prototype.push.apply(target, partial);
// the timeout will ensure that your next render won't occur before the delay
return $timeout(function(){}, delay);
}
// _.chunk is a Lodash function that takes an array and chops it into smaller chunks.
// 'renderSize' is the size of these chunks.
var partials = _.chunk(source, renderSize);
var next;
// here we schedule renders to occur only after
// the previous render is finished through the use of $q promises
_.forEach(partials, function(partial) {
next = scheduleRender.bind(null, partial);
promise = promise.then(next);
});
}

I am using MVC 4 and angularjs in this actually I want to call an angular js function on page load

i want to invoke angularjs function (DeptSpecific) on page load and am passing ID as the parameter which is hard coded. And that i am passing via ng-init="DeptSpecific('1')". I am learning angularjs please suggest me how to call a function and pass a parameter to it on page load without any click or anything just when a page load a function should be called. If you are thinking why i used ng-init ..there is no specific reason for this it might be wrong but it calls the function well i can see that in debugger (f12) but $scope.s i undefined even though there is a matched ID.
$scope.DeptSpecific = function (ID) {
var BelongsToThisDepartment = [];
$http.get('/Department/getDept').success(function (response) {
$scope.departments = $scope.$eval(response);
});
angular.forEach($scope.departments, function (item1) {
if (item1.ID == ID) {
BelongsToThisDepartment.push(item1);
}
})
$scope.s = $scope.$eval(angular.toJson(BelongsToThisDepartment));
// console.log(JSON.stringify($scope.s));
}
<div ng-app="MyApp">
<div ng-controller="MyController">
<table class="tableData" border="0" cellspacing="0" cellpadding="0" ng-init="DeptSpecific('1')">
<thead>
<tr>
<th></th>
<th>ID</th>
<th>NAME</th>
<th>LOCATION</th>
</tr>
</thead>
<tbody ng-repeat="O in s">
<tr ng-class-even="'even'" ng-class-odd="'odd'">
<td class="CX" ng-click="student(O.ID)"><span>+</span></td>
<td>{{O.ID}}</td>
<td>{{O.Name}}</td>
<td>{{O.Location}}</td>
</tr>
Looking at your code, using ng-init is fine, but your $scope.departments may not be accessible outside of the .success method.
angular.module('MyApp')
.controller('MyController', ['$scope', function($scope) {
$scope.DeptSpecific = function (ID) {
var BelongsToThisDepartment = [];
$http.get('/Department/getDept')
.success(function (response) {
$scope.departments = $scope.$eval(response);
angular.forEach($scope.departments, function (item1) {
if (item1.ID == ID) {
BelongsToThisDepartment.push(item1);
}
})
$scope.s = $scope.$eval(angular.toJson(BelongsToThisDepartment));
console.log($scope.s);
});
}
}]);
now if that works for you but you also want to be able to access $scope.s outside of that .success;
You can write a function, add it into .success pass the value returned onSucess, and do what you want to do.
.success(function(response) {
callAFunction(response);
}

angular edit details using REST($resource) Service

I have a table with result set and there is edit option existing in each row. After clicking on the 'edit' link, i am able to populating the content on the fields.
But how do i edit the existing content using REST Service.
<table class="table-bordered table">
<thead>
<tr>
<th>id</th>
<th>Director</th>
<th>genre</th>
<th>releaseYear</th>
<th>title</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="result in results | orderBy:'_id'">
<td>{{result._id}}</td>
<td>{{result.director}}</td>
<td>{{result.genre}}</td>
<td>{{result.releaseYear}}</td>
<td>{{result.title}}</td>
<td>Edit | Delete</td>
</tr>
</tbody>
</table>
controller
$scope.saveContact = function(){
//save or edit contact
};
I have created in plunker.
content EDIT using REST API
I put it into work. You were close to the solution.
Here is the working plunker
What i did :
1 - I changed your way of getting the element for the form.
HTML
//I give the complete object instead of the id
ng-click="edit(result)"
Controller
//I prefer to pass the entire object
$scope.edit = function(result){
$scope.cineresultsFrm = angular.copy(result);
};
Service
I just removed the service. It wasn't useful anymore.
2 - I used the method of the ressource on your object
Controller
$scope.saveContact = function(){
//The function given to $update() is the .then() function
$scope.cineresultsFrm.$update(function(){
//If the update succeed i update the whole list. Could be done a better way but if you don't have any performance issues that will do the job.
$scope.getMovies();
});
};
I also changed the way you handle the "then" in the promise. But this is just a matter of taste.
$scope.getMovies = function(){
$scope.movieResults = movie.query(function() {
$scope.results = $scope.movieResults;
});
};
$scope.getMovies();
Hope it helped you

Angular ng-repeat how to unwrap promise in template for each item

In the past promises returned by a functon used to be able to be bound to a template and when the promise was resolved the value would update automatically in the template. However, I've read that this automatic unwrapping of promises no longer exists.
I've provided simplified code below to give the idea of what I am trying to do. My controller has a dataArray containing objects. Each object contains an id field. The controller has a function that takes the id and returns a promise of some data. In the template I am using an ng-repeat to loop through each object (obj) in dataArray and I want to bind to the resolved value of the promise that getData returns for each obj. However, when I do this, I get the "10 $digest() iterations reached. Aborting!" error which I've read is due to the fact that promises can no longer be bound to a template due to the lack of promise unwrapping.
Controller:
myApp.controller('myCtrl', function($scope, dataStore) {
$scope.someDataArray = dataArray; // an array of objects
// returns a promise to provide data for the supplied id
$scope.getData = dataStore.getData(id);
})
Template:
<div>
<table>
<thead>
....
</thead>
<tbody>
<tr ng-repeat="obj in dataArray">
<td>{{obj.item1}}</td>
<td>{{getData(obj.id)}}</td>
</tr>
</tbody>
<table>
<div>
Does anyone have a good method for passing a value from an array of values in an ng-repeat to a function that returns a promise so that when the promise resolves the value is updated in each table cell of the template?
I know that if I was doing this for a single value I could create a variable for the value on the scope and use the then() function of a promise to set the value. The template would bind to this value. However, as I am using an ng-repeat there will be separate function calls for every obj.id in dataArray.
Well, I personally don´t think that making that call from the view is a good practice.
I would separate things out, in the view, bind to a property that is going to be populated by the resolved promise:
<div>
<table>
<thead>
....
</thead>
<tbody>
<tr ng-repeat="obj in dataArray">
<td>{{obj.item1}}</td>
<td>{{obj.data)}}</td>
</tr>
</tbody>
<table>
<div>
And on my controller I would make the call to getData() for every item of the array, to make it even better, I´d use a watch so every time my array gets updated I´d make sure that the calls to getData() are performed
myApp.controller('myCtrl', function($scope, dataStore) {
$scope.$watch('someDataArray ', function(newArray) {
for(var i=0; i<newArray.length; i++){
populateData(newArray[i]);
}
});
var populateData = function(obj){
dataStore.getData(obj.id).then(function(value){
obj.data = value;
});
}
$scope.someDataArray = dataArray; // an array of objects
});
I haven´t tested this out, but that´s the general idea. Hope that helps.
Fetch the data in your controller:
$scope.fetchedData = [];
$q.all($scope.someDataArray.map(function(obj) {
return dataStore.getData(obj.id);
}).then(function(array) {
$scope.fetchedData = array;
});
And in the view, display the fetched data:
<tr ng-repeat="obj in dataArray">
<td>{{obj.item1}}</td>
<td>{{ fetchedData[$index] }}</td>
</tr>

AngularJS calling a function inside a controller with ng-click

I've got a problem with getting my function inside my controller to work properly.
given the following partial:
<div ng-controller="KundeDetailCtrl"><table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>InstallationsID</th>
</tr>
</thead>
<tbody >
<tr data-ng-repeat="mandant in kunde.mandanten" ng-click="getMandant(mandant)" >
<td> {{mandant.name}}</td>
<td>{{mandant.id}}</td>
</tr>
</tbody>
</table></div>
I want to be able to click on one row and call the appropriate function in my controller:
var AppControllers = angular.module('AppControllers', []);
AppControllers.controller('KundeDetailCtrl', ['$scope', '$routeParams', 'Kunde',
function($scope, $routeParams, Kunde) {
$scope.kunde = Kunde.get({kundeId: $routeParams.kundeId}, function(kunde) {
});
$scope.getMandant = function(id){
for(var i= 0, l=$scope.kunde.mandanten.length; i<l; i++){
if($scope.kunde.mandanten[i].id == "id")
{
$scope.mandant = $scope.kunde.mandanten[i];
}
}
Location.href='index.html#/kunden/{{kunde._id}}/module'
};
}]);
Actually, I only want to know which row was clicked and hand the object of the clicked row to the next partial which is supposed to display some other data.
The ng-click does not seem to do anything at all. In the console I only see getMandant: null
Can anyone help me with this?
It seems you are comparing the id in the mandaten list to the string "id" rather than the object id:
if($scope.kunde.mandanten[i].id == "id")
You should also consider using === rather than ==, it is the preferred way to compare things in javascript.
It appears you are redirecting to another view in your angular application, any reason not to use the $location service?

Resources