push method in Array not working - Angular 2 - arrays

I am stuck with this piece of code for last 4 hours, unable to figure out what's the issue. It's written in typescript.
the newsa array is to be filled with the data I've pulled using the api. but instead, it shows errors like can't find push property, after I declare the array properly with all needs like the public prefix and all. There is no error but nothing is getting pushed. What's wrong.
It would be great help if you answer.
public newsa: Array<any> = [];
fetchNews() {
console.log("Fetch NEws has started");
var that = this;
let googlenewsUrl:string;
let finalUrl: string;
this.countries.forEach(function(i) {
googlenewsUrl = "https://news.google.com/news?q=" + i.name.replace(/\s+/g, '') + "&output=rss";
finalUrl = '//ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=50&callback=JSONP_CALLBACK&q=' + encodeURIComponent(googlenewsUrl);
that.jsonp.get(finalUrl).toPromise().then(news => that.newsa.push(news)).catch(that.handleError);
});
}

Instead of
function(i)
use
(i) =>
to retain the scope of this

Related

Why can't I update its element value correctly within Array.forEach() loop in Angular 7?

I'm testing Material Table(mat-table) on Angular 7, here's a weird issue I ran into.
Send a request to jsonplaceholder for fake data in users.service
export class UsersService {
API_BASE = 'https://jsonplaceholder.typicode.com/users';
constructor(private http: HttpClient) {}
getUsers(): Observable<object> {
const url = this.API_BASE;
return this.http.get(url);
}
}
Because jsonplaceholder only returns 10 rows of data, so I concatenate the data for a larger array, say, 30 rows for testing pagination feature with ease. Meanwhile, update the 'id' field with iterate index so the 'id's looks like 1,2,3...30, instead of 1,2,3...10,1,2,3...10,1,2,3...10, which is a result of concatenation, that's it, nothing special.
users.component:
ngOnInit(): void {
this.userService.getUsers().subscribe((users: UserData[]) => {
users = users.concat(users, users);
users.forEach((user, index) => (user.id = index +1));
console.log(users);
this.dataSource.data = users;
});
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
Although the table shows up beautifully, but the 'id's column looks weird, they are not 1,2,3...30 sequentially, instead, they are 21,22,23...30,21,22,23...30,21,22,23...30
I tried to print out the user.id inside the forEach loop, it's all good.
users.forEach((user, index) => {
user.id = index + 1;
console.log(user.id);
});
Where did I go wrong with this? Any clue? Thanks.
P.S, API used in the code: https://jsonplaceholder.typicode.com/users
even though you have 30 array elements after concatenating the array twice, you still only have 10 unique objects. the Object behind users[20] is the same as users[0], so you override the id of the already processed objects from index 10 to 29
you can fix this by creating a copy of each object. There are many ways too do this. a very simple way is serializing and deserializing using JSON.stringify and JSON.parse:
users.forEach(user => users.push(JSON.parse(JSON.stringify(user))));

angular.fromJson not working properly

The code is as follows
var taskString = window.localStorage['tasks'];
if(taskString) {
var tasks = angular.fromJson(taskString);
console.log(tasks);
}
I had a json format string stored in the window.localStorage['tasks'], which is like this
[{"title":"a"},{"title":"b"},{"title":"c"}]
so that the var taskString would be exactly [{"title":"a"},{"title":"b"},{"title":"c"}]
in the code I tried to parse this string into a json array tasks, and the array should contain three objects with the title attribute set separately as a, b and c
but the problem here is, after the execution of angular.fromJson(taskString), I print the array out to the console, and in the array the titles become b,c, and undefined
Is this a bug of that funciton? Or did I mistankenly do something I shouldn't have in my code?
Thanks
It seems to work fine. Look at the following example snippet. I emulated localStorage as storage.
Check for any silly mistakes or if you are setting it properly.
var storage = {
setItem: function(name, item) {
this[name] = item
}
}
storage.setItem('tasks', '[{"title":"a"},{"title":"b"},{"title":"c"}]')
var taskString = storage['tasks'];
if (taskString) {
var tasks = angular.fromJson(taskString);
console.log(tasks);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
var json = '[{"title":"a"},{"title":"b"},{"title":"c"}]';
var obj = angular.fromJson(json);
console.log(obj);
Works fine for me, below is the fiddle:
http://jsfiddle.net/n8ezb7sg/89/

Angular2 Tutorial: How is the ID variable in this section being auto incremented?

In This Section of the Angular2 Tutorial there is functionality to add new items to the array. When added, the ID is automatically incremented but I can't figure out what process is doing that.
I know that Arrays.push() returns the length of the array, is that length automatically inserted into the id variable in the Hero class?
In hero.services.ts there is this block of code to create a hero:
create(name: string): Promise<Hero> {
return this.http
.post(this.heroesUrl, JSON.stringify({name: name}), {headers: this.headers})
.toPromise()
.then(res => res.json().data)
.catch(this.handleError);
}
In the heroes.component.ts there is the add
add(name: string): void {
name = name.trim();
if (!name) { return; }
this.heroService.create(name)
.then(hero => {
this.heroes.push(hero);
this.selectedHero = null;
});
}
The tutorial is using the angular 2 in-memory-web-api library. It is handling the post that is being made to the heroes url. The handler can be seen in this file on line 328:
https://github.com/angular/in-memory-web-api/blob/master/in-memory-backend.service.js
Inside that handler the id is generated via a call to the genId function whose implementation is on line 257:
InMemoryBackendService.prototype.genId = function (collection) {
// assumes numeric ids
var maxId = 0;
collection.reduce(function (prev, item) {
maxId = Math.max(maxId, typeof item.id === 'number' ? item.id : maxId);
}, null);
return maxId + 1;
};
It uses the default functionality of InMemoryDbService .
You can find the mock/reference in app/in-memory-dataservice.ts
import { InMemoryDbService } from 'angular2-in-memory-web-api
The angular source for the service can be found here: in-memory-backend.service.t (line 326)
In the create method of the service, a web api gets called and posted the hero's name to it, returning a full hero object with id and name fields.
So I guess the incrementing and "saving" happens behind the curtains at that web api.

Remove a value from Firebase Array

I have a array in firebase created using the push() function.
I am trying to remove a specific value in that array.
var arr = $firebaseArray(ref.child('invoices').child('pending').child(coId));
arr.$loaded().then(function(){
var index = arr.$getRecord(invoiceId);
arr.$remove(index);
})
However, this is not working. I keep getting -1 for the var index. If there is an easier way to remove a value, with or without angularFire, I would be open to it.
Thanks!
I made a plunker for your case and it works:
var ref = new Firebase('https://benjaminsuch.firebaseio-demo.com/'),
arr = $firebaseArray(ref.child('invoices'));
arr.$loaded().then(function() {
var index = arr.$getRecord('item123423');
console.log('index', index);
arr
.$remove(index)
.then(function() {
console.log('item removed')
})
.catch(function(error) {
console.log('error', error);
});
});
Maybe you provide us a plunker too with your code, so we can see whats going on.

get nested object length in an angularFire array in Firebase

I have a Firebase structure like this:
user {
uid {
Lessons {
lid1 {
Title: ...
}
lid2 {
Title: ...
}
}
}
}
I want to use AngularFire to convert user as array so I can filter them using Angular like this:
var usersRef = new Firebase($rootScope.baseUrl + "users");
var userListfb = $firebase(usersRef).$asArray();
The problem is, I also need the number of child of the Lessons object. When I log the userListfb, it is an array. But inside the array, the Lessons node still an object. I can not user length to get its length. What is the correct way to find out the number of child of the Lessons Node with Firebase AngularFire?
Edit 1
According to Frank solution, I got an infinite loop (digest circle error from AngularJS).
The problem is, I will not know the "uid" key. I need to loop it in the first array to get the uid into the second firebaseArray.
Let's say I have a ng-repeat="user in users" in the view and call this on view level in each repeat:
{{getLessonLength(user.uid)}}
Then in the controller, I have this function:
$scope.users = $firebaseArray($scope.usersRef);
$scope.getLessonLength = function (uid) {
var userRef = $rootScope.baseUrl + "users/" + uid + "/lessons/";
var lessonsNode = $firebaseArray(new Firebase(userRef));
return lessonsNode.length;
}
}
And it throw this error: Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
All I want it is something like var lessonsCount = snapshot.child('lessons').numChildren() in regular Firebase .on('child_added' ...), the numChildren() function in FirebaseArray. Please help!
AngularFire contains quite some code to ensure that an ordered collection in your Firebase maps correctly to a JavaScript array as Angular (and you) expect it.
If you have a reference to a specific user, you can just create a new sync ($firebase) and call $asArray on that.
var usersRef = new Firebase($rootScope.baseUrl + "users");
var userListfb = $firebase(usersRef).$asArray();
var uid1LessonsRef = userRef.child('uid1').child('Lessons');
var uid1LessonsArray = $firebase(uid1LessonsRef).$asArray();
uid1LessonsArray.$loaded().then(function(arr) {
console.log('Loaded lessons, count: '+arr.length);
});
The data will only be synchronized once, no matter how many references you create to it.

Resources