How to generate array properties with some default value when doing ng repeat?

Below is my array:

$scope.parent.cars1 = ["Saab", "BMW"]; // There are more than 1000 records in this array $scope.child.Cars1 = []; 

Now I am trying to assign $scope.parent.cars1 to $scope.child.Cars1 , but would like to have 3 properties in my $scope.child.Cars1 , i.e. the name, operation, and the selected , and by default, the operation property will be 1 and selected will be true.

Code:

 $scope.child = {}; if ($scope.child.Cars1 == undefined) $scope.child.Cars1 = []; angular.forEach($scope.parent.Cars1, function(obj, key) { $scope.child.Cars1.push({ name: obj, operation: 1, // this value is used to tick all radio button of clear and save selected: true // this value is used to check all checkbox to true by default }); }) 

Now that my $scope.parent.cars1 contain thousands of entries, my browser freezes because I use this $scope.child.Cars1 in my view to display the entries, as shown below:

 <tr ng-repeat="item in child.Cars1 | myfilter : searchitem"> <td> <input ng-model="item.selected" type="checkbox" name="a{{$index}}" id="a{{$index}}"> </td> <td> <div> <input type="radio" ng-model="item.operation" value="0" name="b{{$index }}" id="b{{$index}}">Clear </div> <div> <input type="radio" ng-model="item.operation" value="1" name="b{{$index }}" id="b{{$index}}">Clear and Save </div> </td> </tr>; 

Update: I am trying to avoid the process described below so that the browser cannot hang itself due to the huge number of entries:

 angular.forEach($scope.parent.Cars1, function(obj, key) { $scope.child.Cars1.push({ name: obj, operation: 1, // this value is used to tick all radio button to true by default selected: true // this value is used to check all checkbox to true by default }); }); 

Plunker

Using @Bear plunker, this happens:

enter image description here

+5
source share
6 answers

I have update and clear my PLUNKER with real 8000 entries ...
I have to say that if you don't use pagination about any technique that writes a certain number of entries to the DOM, you probably have a bad job.

As a tip to improve a better job:

  • Try to do as much work as you can in local vars before array binding
  • Working with a local copy of the entire array and linking only the number of entries on the screen. (Use javascript slice(start, end) )
  • add track by $index ( angular docs ng-repeat )
  • When you are using angular 1.3+, disable two-way data binding if it is not necessary ( one-way data binding angularJs )

My code is:

JS CONTROLLER:

 var bigArray = ["Dandai", "Immātīn", "Oefatu" ...]; var itemsLocal = []; //Local copy of the items to work var PAGE_SIZE = 250; var TOTAL_RECORDS = bigArray.length; var start = 0; var end = PAGE_SIZE; $scope.items = []; //Items to repeat in screen $scope.loadData = loadData; $scope.prevPage = prevPage; $scope.nextPage = nextPage; transformData(); loadData(); function transformData() { for (var i = 0; i < TOTAL_RECORDS; i++) { itemsLocal.push({ name: bigArray[i], selected: true, operation: 1 }); } } function loadData() { $scope.items = itemsLocal.slice(start, end); //repeat only certain part of the data } function prevPage() { if (start < PAGE_SIZE) return; start = start - PAGE_SIZE; end = end - PAGE_SIZE; loadData(); } function nextPage() { if (end >= TOTAL_RECORDS) return; start = start + PAGE_SIZE; end = end + PAGE_SIZE; loadData(); } 

HTML:

 <div> <button type="button" ng-click="prevPage()">Load Previous</button> <button type="button" ng-click="nextPage()">Load Next</button> </div> <hr/> <table class="table"> <thead> <tr> <th>Column 1</th> <th>Column 2</th> </tr> </thead> <tbody> <tr ng-repeat="item in items track by $index"> <td> <input ng-model="item.selected" type="checkbox"> {{ item.name }} </td> <td> <div> <input type="radio" class="radio-custom" ng-model="item.operation" value="0">Clear </div> <div> <input type="radio" class="radio-custom" ng-model="item.operation" value="1">Clear and Save </div> </td> </tr> </tbody> </table> 
+7
source

You can use Array.map () to iterate through the array.

For my own testing, I created an array ( $scope.array1000 ) with 1000 records, and it booted without problems (freezing, longer loading time, etc.).

Demo

 var app = angular.module('myApp', []); app.controller('MyCtrl',function($scope) { $scope.parent = { "cars1": ["Saab", "BMW"] }; $scope.array1000 = []; for (var i=0; i< 1000; i++) { $scope.array1000.push($scope.parent.cars1[0]+''+i); } var res = $scope.array1000.map(function(record) { return { "name": record, "operation": 1, "selected": true } }); console.log(res); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="myApp" ng-controller="MyCtrl"> <div ng-repeat="item in array1000"> {{ item }} </div> </div> 
+5
source

Your problem is not data initializing , which makes the browser slowly too, the main problem is manipulate DOM element with huge data in one stream, then the browser looks like it hangs up. So you have to make part of the data from the huge data at a time. You can use the $interval service because I never used angularjs , this problem spent me most of the night, but I think it's worth it.

 // Instantiate the app, the 'myApp' parameter must // match what is in ng-app var myApp = angular.module('myApp', []); function timeFormat(time) { var units = ['ms', 's', 'm']; var radix = [1000, 60, 60]; for (var i = 0; i < units.length; i++) { if (time < radix[i]) { return time.toFixed(2) + units[i]; } time /= radix[i]; } return time + 'h'; } function run(name, fn) { var start = +new Date; var result = fn.call(this); function timeElapsed() { var elapsed = +new Date - start; console.log(['Stage[' + name + ']', 'elapsed', timeFormat(elapsed)].join(' ')); } if (typeof result.then == 'function') { result.then(timeElapsed); } else { timeElapsed(); } return result; } myApp.controller('ToddlerCtrl', function ($scope, $timeout, $interval) { var cars = run('initializing data', function () { var DATA_SIZE=1000; var cars = []; for (var i = 0; i < DATA_SIZE; i++) { cars.push(i); } return cars.map(function (_, i) { return 'car-' + i; }).map(function (name) { return { name: name, operation: 1, selected: true }; }); }); $scope.className = 'loading'; //initialing cars for rendering $scope.cars = []; var BATCH_SIZE = 30; var batches = Math.floor(cars.length / BATCH_SIZE); var DELAY = 1; var push = Array.prototype.push; var task = run('filling data', function () { function fill() { push.apply($scope.cars, cars.splice(0, BATCH_SIZE)); //rendering data into browser console.log('Remaining ' + cars.length + ' items ...'); } fill(); return $interval(fill, DELAY, batches); }).then(function () { $scope.className = 'hidden'; }); }); 
 ul, li, html, body { margin: 0; padding: 0; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } ul { list-style: none; } .loading { font-size: 2em; font-weight: bold; position: fixed; right: 20px; top: 20px; color: green; } .hidden { display: none; } .loading em { position: relative; display: inline-block; height: 1em; width: 50px; } .loading span { position: absolute; text-overflow: clip; -webkit-animation: loading 1s infinite linear; -o-animation: loading 1s infinite linear; animation: loading 1s infinite linear; } @keyframes loading { from { clip: rect(0, 0, 50px, 0); } to { clip: rect(0, 50px, 50px, 0); } } @-o-keyframes loading { from { clip: rect(0, 0, 50px, 0); } to { clip: rect(0, 50px, 50px, 0); } } @-webkit-keyframes loading { from { clip: rect(0, 0, 50px, 0); } to { clip: rect(0, 50px, 50px, 0); } } .loading:first-letter { font-size: 1.5em; } li { float: left; width: 21%; border: 2px solid #eee; margin: 10px 2%; padding: 5px; } .car { padding: 5px 0 10px; display: block; } .button-group { text-align: right; } 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script> <main ng-app="myApp"> <div ng-controller="ToddlerCtrl"> <div ng-class="className" class="loading">Loading <em><span>...</span></em></div> <ul> <li ng-repeat="item in cars"> <label class="car"> <input ng-model="table.selected" type="checkbox" name="a{{$index}}" id="a{{$index}}">{{ item.name }} </label> <div class="button-group"> <label> <input type="radio" ng-model="item.operation" value="0" name="b{{$index }}" id="b{{$index}}"> Clear </label> <label> <input type="radio" ng-model="item.operation" value="1" name="b{{$index }}" id="c{{$index}}"> Clear and Save </label> </div> </li> </ul> </div> </main> 
+4
source

something like .. ?? .. hope this helps

 $scope.child = {}; if ($scope.child.Cars1 == undefined) $scope.child.Cars1 = []; var all = angular.copy($scope.parent.Cars1); var test = []; angular.forEach(all, function (obj, key) { test.push( { name: obj, operation: 1, // this value is used to tick all radio button of clear and save selected: true // this value is used to check all checkbox to true by default } ); $scope.child.Cars1 = test; }) 

This way you are not working with $ scope vars (the reason is haeavy and freeze UI) ...

+3
source

Well, the plunker had a lot of mistakes. I assume that you created it in a hurry to demonstrate a code example.

Without actually viewing your actual files with actual data, it is very difficult to point out the problem.

Try using the simple array.map() function. Check this out http://plnkr.co/edit/Sx3lMIBEMMj4xrOBI5vI?p=preview

The display function in your array, which returns an object, arranges the data in the required form.

If the hang is due to js bottlenecks, it can solve the problem. Otherwise, try a simple loop that iterates through the array. A for loop is the fastest and most efficient way to loop through an array, since there is no overhead to calling a function.

However, more than 1000 DOM elements can cause the browser to freeze. If my plunker can handle it, try showing only part of the complete data at a time.

This can be done with a simple pagination, which only displays a page with a certain number of records at a time.

Or you can use directives like virtual repeat.

Even endless scrolling of the DOM buffering method.

Fully dependent on the use case.

+3
source

The reason for the slowness will most likely be the filter: ng-repeat="item in child.Cars1 | myfilter : searchitem" .

An array of child.Cars1 objects will be created pretty quickly.

+3
source

Source: https://habr.com/ru/post/1264949/


All Articles