An (edited for readability) version of my json looks like this.
It's actually the reddit front page in json form:
{
"kind": "Listing",
"data": {
"modhash": "fb7jljbeer6a0dbec0b7b939c890078b5a92d221b3e2b31cec",
"children": [
{
"kind": "t3",
"data": {
"subreddit": "gifs",
"id": "66wssv",
"author": "GuacamoleFanatic",
"name": "t3_66wssv",
"subreddit_name_prefixed": "r/gifs",
"domain": "gfycat.com",
"thumbnail": "https://b.thumbs.redditmedia.com/E4FB3khTGQ_D8KP-P7KEVXpB9MzY_XDWUhtPmGnNOuE.jpg",
"subreddit_id": "t5_2qt55",
"permalink": "/r/gifs/comments/66wssv/8_year_old_tillys_first_couple_of_seconds_wearing/",
"url": "https://gfycat.com/VacantRequiredAmethystinepython",
"title": "8 year old Tilly's first couple of seconds wearing a bionic hand.",
"created_utc": 1492877987,
"num_comments": 504,
}
},
{
"kind": "t3",
"data": {
"subreddit": "IAmA",
"id": "66wut7",
"author": "JoergS",
"name": "t3_66wut7",
"subreddit_name_prefixed": "r/IAmA",
"domain": "self.IAmA",
"thumbnail": "self",
"subreddit_id": "t5_2qzb6",
"permalink": "/r/IAmA/comments/66wut7/iama_jörg_sprave_the_bald_crazy_german_who_runs/",
"url": "https://www.reddit.com/r/IAmA/comments/66wut7/iama_jörg_sprave_the_bald_crazy_german_who_runs/",
"title": "IamA (Jörg Sprave, the bald crazy German who runs \"The Slingshot Channel\" on YouTube.) AMA!",
"created_utc": 1492878607,
"num_comments": 781,
}
},
The controller is very simple:
angular.module('redditdupe').controller('frontPage', ['$scope', '$http', '$routeParams',
function frontPage($scope, $http){
$http({
method: 'GET',
url: 'https://www.reddit.com/.json'
})
.
then(
function successCallback(response)
{
$scope.children=response.data.data.children;
}
,
function errorCallback(response) {
}
);
}]);
And so is the html:
<div class="cartouche" ng-repeat="child in children">
<div ng-repeat="data in child">
<img src="{{ data.thumbnail }}"><br>
{{ data.title }} ({{ data.domain }})<br>
{{ data.created_utc * 1000 | date:'yyyy-MM-dd HH:mm:ss Z' }} {{data.author}} {{ data.subreddit_name_prefixed }}<br>
{{ data.num_comments }}<br>
</div>
</div>
However, ng-repeat shows
a blank set of results, followed by
a real set of results,
followed by another blank set,
followed by another real set
... and so on
Like this:
<--- blank line
() <--- probably the domain gfycat.com, except it's blank
null < --- dunno
<--- probably the comment count, but is blank line
8 year old Tilly's first couple of seconds wearing a bionic hand. (gfycat.com)
2017-04-22 09:19:47 -0700 GuacamoleFanatic r/gifs
1959
() <--- then the same shenanigans again
null
Seen at the March for Science (i.redd.it)
2017-04-22 09:45:18 -0700 Polymathyx r/pics
338
I've googled a lot and this doesn't seem to fit the "consumption cycle" explanation because it's not that the entire collection is displayed in sequence once, and then twice.
This is each element being cycled twice individually, first blank then filled out.
I've been slamming my head against the desk for days.
What is the cause and, more importantly, what is the solution please?
Very grateful for any suggestions.
Related
In my laravel controller I wrote:
public function index()
{
$products = Product::all(); // get all products
$products['page_title'] = 'Demo Products'; // page title
return response()->json($products);
}
And in Angular 4, I wrote for this:
constructor(private productService: ProductService, private title: Title) { }
ngOnInit() {
//console.log('data');
this.productService.getProducts()
.subscribe(data => {
this.products = data;
this.title.setTitle(data.page_title);
},
And in the html under the angular I wrote the following:
<article class="col-md-4" *ngFor="let product of products">
<div class="font-weight-bold">{{product.product_name}}</div>
<p>{{product.description}}</p>
<p>{{product.rating}}</p>
</article>
In index.html, I wrote <title></title>
It shows the console error as below:
ProductComponent.html:7 ERROR Error: Error trying to diff '[object
Object]'. Only arrays and iterables are allowed
In postman, I see the following:
"18": {
"id": 19,
"product_name": "Adam Walsh",
"description": "Rabbit coming to look for her, and the small ones choked and had just upset the week before. 'Oh, I BEG your pardon!' cried Alice in a shrill, loud voice, and see after some executions I have to ask.",
"rating": 0,
"price": 59.2,
"created_at": "2018-03-22 11:04:39",
"updated_at": "2018-03-22 11:04:39"
},
"19": {
"id": 20,
"product_name": "Marilyne Kulas II",
"description": "I want to stay in here any longer!' She waited for a minute or two sobs choked his voice. 'Same as if his heart would break. She pitied him deeply. 'What is it?' he said, turning to Alice an.",
"rating": 5,
"price": 13.5,
"created_at": "2018-03-22 11:04:39",
"updated_at": "2018-03-22 11:04:39"
},
"page_title": "Demo Products"
}
The error is sent because *ngFor requires an array to iterate.
Assigning $products['page_title'] as if $products was an associative array is wrong. $products is a Illuminate\Database\Eloquent\Collection. When sending it as json, Laravel parse it as an indexed array. But i guess you broke it by assigning 'page_title' this way.
Try to print_r($products) before sendind it, to check that.
I'd rather do something like this :
return response()->json(['data' => $products, 'page_title' => 'Demo Products']);
And in angular :
this.productService.getProducts()
.subscribe(response => {
this.products = response.data;
this.title.setTitle(response.page_title);
},
I have a custom directive called crust:
JS:
.directive('crust', function(){
return{
restrict: 'EA',
replace: true,
scope: {
datasource: '='
},
templateUrl: '../../configurator/partials/crust.html'
}
})
HTML template (crust.html):
<li data-ng-repeat="type in datasource.types">
<input type="radio"
name="{{datasource.id}}"
data-ng-class="radio-selector"
data-ng-true-value="true"
value="true"
data-ng-model="type.selected"
data-ng-change="updatePizza(type)"
id="{{type.id}}">
<label for="{{type.id}}"> <span></span>
<h2 data-ng-bind="type.name"></h2>
<p data-ng-bind="type.description"></p>
</label>
</li>
The Model (crustTypes) is pulled via a service from this JSON:
{
"id": "crt",
"types": [{
"id": "crt1",
"name": "original",
"description": "Our traditional scratch-made crust",
"price": "5",
"selected":"false"
}, {
"id": "crt2",
"name": "thin",
"description": "A light crispier crust",
"price": "6",
"selected":"false"
}, {
"id": "crt3",
"name": "fresh pan",
"description": "A thick buttery crust",
"price": "7",
"selected":"false"
}, {
"id": "crt4",
"name": "stuffed",
"description": "Two layers of original crust",
"price": "8",
"selected":"false"
}]
}
The directive is being invoked in the HTML like so:
<ul>
<crust data-datasource="crustTypes" data-datavalue="pcrustType"></crust>
</ul>
The looping is working fine, and ng-repeat is rendering the list properly. The problem is that I want to assign datasource.id as the common name of the radio group, and due to some reason, datasource.id is coming up as undefined. Consequently, the name is not being assigned and the user is being allowed to enter multiple selections.
If instead I pass type to updatePizza(item) it comes up fine. Its just the parent model that's not being displayed
If I try to return datasource through updatePizza(), it is still coming up as undefined.
I'm sure I'm missing something basic here. Help!
Here is a Plunker of the code
Replace name="{{datasource.id}}" with name="{{$parent.datasource.id}}"
Using the browser, both firefox and chrome, I am able to see my repeated items. However once the app is pushed to the device (android in this case) no results show. I am sure it is iterating through the total results, because I get a blank screen with 51 blank spots. If I don't use the track by $index I get the duplicate error.
I attempted the json.parse(); found here ng-repeater not working for JSON with no results either.
My controller looks like so:
app.controller('DataCtrl', function($scope, $ionicModal, $timeout, $http) {
$http.get('/js/center-forecast.json').
success(function(data, status, headers, config) {
$scope.jsondatas = data.rows;
}).
error(function(data, status, headers, config) {
$scope.jsondatas = "Error. The Report is Not Available at this Time.";
});
});
Loop:
<ion-list>
<ion-item ng-repeat="jsondata in jsondatas track by $index">
{{jsondata.row.name}}
</ion-item>
</ion-list>
EDIT: Just tried {{$index.jsondata.row.name}} and got the same results as the device in the browser. 51 rows with no data.
.json data validates just fine. It is repeating through on the device, but not showing the results in each , just showing a blank . I did check the css to make sure the words are not white. I don't see any results/errors in log.cat either...
Any ideas?
edit: JSON data example:
"rows": [{
"row": {
"id": "AAIC",
"name": "Alaska Avalanche",
"url": "http://www.valdezavalanchecenter.org",
"center_point": "(-146.3053,61.1231)",
"lat": "61.1231",
"lng": "-146.3053",
"icon": "center_i.gif"
}
}, {
"row": {
"id": "PAC",
"name": "Payette",
"url": "http://www.payetteavalanche.org/advisory/",
"center_point": "(-116.095276,44.906469)",
"lat": "44.906469",
"lng": "-116.095276",
"icon": "center.png"
}
}, {
"row": {
"id": "KPAC",
"name": "Flagstaff/Kachina Peaks",
"url": "http://www.kachinapeaks.org/",
"center_point": "(-111.6506,35.1981)",
"lat": "35.1981",
"lng": "-111.6506",
"icon": "center_i.gif"
}
}]
My template:
<div ng-repeat="comment in article.comments">
{{ comment.date }} by {{ comment.author }} <button type="button" ng-click="removeComment($index)">remove</button>
</div>
My JSON comments:
"comments": [
{
"author": "Syl A",
"date": "2014-07-02",
"content": "lol"
},
{
"author": "Syl B",
"date": "2014-07-02",
"content": "lol"
},
{
"author": "Syl C",
"date": "2014-07-02",
"content": "lol"
}
]
My controller:
$scope.removeComment = function (key) {
// This is what I want to remove
// Object {author: "Syl A", date: "2014-07-02", content: "lol", $$hashKey: "004"}
console.log($scope.article.comments[key]);
};
The following snippets is not OK, it does nothing;
$scope.article.comments.splice[key, 1];
The following snippets are not OK, the object is removed but in the view got "by remove", the complete line is not removed and I can't remove more than one item Error: [ngRepeat:dupes]:
$scope.article.comments[key] = undefined;
delete $scope.article.comments[key];
The following snippet is not OK, the object is removed but in the view got "by remove", the complete line is not removed:
$scope.article.comments[key] = {};
So I didn't find a solution on SO to make an "all-in-one" remove, DOM and "data". Why my splice doesn't work here?
You're using splice wrong is the problem.
Update your splice to use ( ) instead of [ ]
$scope.article.comments.splice(key, 1);
Is it normal, that angularjs ng-repeat takes 1.5 Seconds to render data from an rest api? The result consists of only 10 rows with in total 1KB of data. How can I improve the speed or where to look for the problem?
ADDED INFOS:
The rest request itself only takes 128ms if I run it directly on the browser.
This is a set of sample data you get from the rest api:
{
"result": [
{
"id": 1224,
"name": "Schokolade-Vanille",
"kcal": 35500,
"displayName": "Schokolade-Vanille"
},
{
"id": 23423,
"name": "Naturreis Uncle Bens",
"kcal": 34400,
"displayName": "Naturreis Uncle Bens"
},
{
"id": 123231,
"name": "Paprikahendl",
"kcal": 4100,
"displayName": "Paprikahendl"
},
{
"id": 434,
"name": "Vanille Kugeln",
"kcal": 53700,
"displayName": "Vanille Kugeln"
},
{
"id": 323423,
"name": "Weihnachtstraum, Lindor-Kugeln",
"kcal": 60800,
"displayName": "Lindor-Kugeln"
},
{
"id": 5435,
"name": "Schokolade",
"kcal": 4300,
"displayName": "Schokolade"
},
{
"id": 23213,
"name": "Hühner-Nuggets",
"kcal": 23400,
"displayName": "Hühner-Nuggets"
},
{
"id": 5534,
"name": "Knödel, Kartoffel",
"kcal": 1230,
"displayName": "Knödel, Kartoffel"
},
{
"id": 23233,
"name": "Curvers",
"kcal": 15400,
"displayName": "Curvers"
},
{
"id": 53434,
"name": "Frites Original",
"kcal": 14100,
"displayName": "Frites Original"
}
],
"count": 12854
}
NEW ADDED INFOS
I have had a closer look now and found out, that not te repeat funktion is the problem.
I used the following code:
$scope.updateResultset = function() {
$scope.result = Food.query({
offset: $scope.offset,
order_by: $scope.orderby,
name: $scope.textfilter,
},function(){
console.log( "response " + (new Date().getTime() - start) );
});
$scope.offset = undefined;
console.log( "updateResultset " + (new Date().getTime() - start) );start = new Date().getTime();
And get the following response:
response 435
But the request itself only takes 131ms. In my opinion, >300ms is a lot of time to waste in a single method?
Compared to my former version, where I showed a plan html list, which was replaced by jquery ajax response html, its much slower?
As others indicated in the comments, the cause in the code is likely something else aside from ng-repeat. However, here are other options to consider, if speed still seems like an issue for ng-repeat:
quick-ng-repeat directive on github: https://github.com/allaud/quick-ng-repeat
ng-scroll, as part of angular-ui: https://github.com/angular-ui/ui-utils/blob/master/modules/scroll/README.md
Ok, I found out the problem. Not the repeatition of the 10 list items was the problem! As you can see in my question, I return not only the 10 results, but also the total amount of results. In my case it was '"count": 12854'.
On the same page, I have a pagination which was the part which slows down the whole page, since it had to render 1286 pager buttons (~12854/10). Now I only show 10 pager-buttons.