I want to access data inside a list, but I cannot access it using the square brackets []. The getTalonPaie is a function that call the get method from the HttpClient service and it returns me an observable containing multiple values. The problem is when I was to put it in my array, it is not returning me multiples arrays but one weird empty list with data in it.
onSubmit(): void {
this.listeTalonPaie = Array<number>(1);
const test = [1, 2, 3];
this.listeIndividus = this.indS.listeIndividu;
this.listeIndividus.forEach(ind => {
// The function below is returning me an observable (from httpClient.get()) containing
// multiple objects and I want to add them in my array. I used the push method because
// I need a dynamic array since the number of objects returned by the observable is not
// static.
this.rcs.getTalonPaie(ind.id)
.subscribe( data => {
this.listeTalonPaie.push(data.heures);
test2.push(data.heures);
});
});
// The output is [empty] (i)
// 1: 25
// 2: 40
// 3: 36
// length: 4
// __proto__ : Array(0)
console.log('listeTalonPaie ', this.listeTalonPaie);
// The output is [null]
console.log('listeTalonPaie ', JSON.stringify(this.listeTalonPaie));
// The output is undefined
console.log('Un element ', this.listeTalonPaie[0]);
// The output is (3) [1, 2, 3]
console.log('test ', test);
}
I'm not sure if it's the right way to do it. So if you think there is a better method tell me.
So data is an array and you're pushing that array into this.listeTalonPaie (also an array), so you end up with a nested array [[1,2,3]].
Not sure what your intent is but you might want to use concat or spread instead of push.
this.listeTalonPaie = [...this.listeTalonPaie, ...data.heures];
my console.log() was printing me undefined data.
The subscribe method is asynchronous so console.log is running before your data callback gets invoked. Here's a tiny simulation of it:
// mock subscribe implementation
const subscribe = (callback) => {
// wait half a second then invoke callback with some data
setTimeout(() => callback([1,2,3]), 500);
}
let result = [];
subscribe(data => {
result = [...data];
console.log('1:', result);
});
console.log('2:', result); // <-- called before 1
The problem is with the subscription syntax. I think you should make a new function below and provide it to the subscription.
this.rcs.getTalonPaie(ind.id)
.subscribe( data => {
this.listeTalonPaie.push(data.heures);
this.logDataList(data)
});
});
logDataList(data: any) { console.log(data) };
If it possible you can pull data in ngOnInit and then you have an easy way to get data from your variable when you run onSubmit function
I found that there was no actual problem. In fact, my list works, but my console.log() was printing me undefined data. If someone could explain me why I get undefined data in the console instead of the real value I would be happy !
Related
I have created one service to load all the files data:
readonly file= new BehaviorSubject(null);
readonly file$ = this.pnlNumbers.asObservable();
getFile(filename: string) {
this.file.next(null);
this.subscriptions.push(this.http.get(`/file/${filename}).subscribe(data => {
this.file.next(data);
}, error => {
this.file.next(error);
}));
}
This will return an single object with file information ,eg:
{
id:0001,
name: 'test_file.txt',
...
}
I have created ab function to store all the result data that comes from the getFile service:
getAllFiles(): any {
let filesList= [];
this.activeFilesList.forEach(fileName => {
this.fileService.getFile(fileName);
});
this.fileService.file$.subscribe((data) => {
if (data) {
fileList?.push(data);
}
});
return filesList;
}
I don't know why , but "typeOf this.getAllFiles()" will return an Object instead of Array, for that reason I cant access the indices of filesList[], eg on chrome console:
[]
1:{id:0001,name:'test.file.text'}
2:{id:0002,name:'test.file2.text'}
3:{id:0003,name:'test.file3.text'}
the filesList.lenght = 0
I need that this filesList[] be a type of Array instead of an Object.
Few things here:
Firstly, a common JavaScript gotcha is the return type of an array is in fact 'object'
typeof [] // 'object'
typeof ['any array contents'] // 'object'
i.e. typeof is an ineffective heuristic for determining whether the return type of this function is an array. Use Array.isArray instead:
Array.isArray(['any array contents']) // true
Array.isArray({ someKey: 'someValue' }) // false
Secondly, am I safe to assume that this line
readonly file$ = this.pnlNumbers.asObservable();
Should instead be
readonly file$ = this.file.asObservable();
otherwise the rest of the code does not really have much relevance, as this.pnlNumbers is not referenced anywhere else
Thirdly, it appears that you are trying to combine the results of multiple asynchronous streams (in this case http calls) into a single array to be returned from getAllFiles(). As these are asynchronous, they by nature take some time to return their data. While this data is being returned, the rest of your synchronous function code will run, and that means your return statement will be hit before the http calls have returned their data.
In its current state, getAllFiles() is simply returning the value of filesList before any of the http calls have returned their values, i.e. the default value it was assigned, [].
What you will need to do instead is to
Use an RxJs operator to combine those independent http streams into one stream
Subscribe to this combined stream and handle the combination of values as is appropriate for the operator being used
An example implementation using forkJoin is here, but depending on your use case, other joining operators like concat, mergeMap, combineLatest etc may be preferable:
type FileType = { id: number; name: string }
getAllFiles$(): Observable<FileType[]> {
const filesListObservables: Observable<FileType>[] =
this.activeFilesList
.map(
(fileName: string) => this.fileService.getFile(fileName)
);
const filesList$: Observable<FileType[]> = forkJoin(filesListObservables);
return filesList$;
}
getAllFiles(): void {
this.getAllFiles$()
.subscribe(
(allFiles: FileType[]) => {
console.log(allFiles) // [{id:0001,name:'test.file.text'},...]
}
)
}
Hello so I am creating a filter search and I 'm trying to collect all the key (tags) that the user press, inside an array, however every time that a new value is push it does override the entire array. So I tried a couple of things, like spread syntax, concat, etc. But with no luck.
So my action looks like this:
const setCurrentFilters = async (context, payload) => {
if (payload) {
context.commit('setCurrentFilter');
}
}
My state
state:{
filters: JSON.parse(sessionStorage.getItem('currentFilters') || '[]'),
}
The mutation
setCurrentFilter(state, payload) {
state.filters.push(payload);
sessionStorage.setItem('currentFilters', JSON.stringify(payload));
}
And my getter
currentFilters(state) {
return state.filters;
},
Thank you in advance for any help : )
This is simply because you set const filters = []; which means that the next condition if (filters.length) will always return false (as you just created this array) and therefore the else statement will execute.
in the else statement you basically push the new payload to the empty array you just initialized - which makes your array always hold only the new value
i believe that you just need to remove the const filters = []; line, and access the filters property that exists in your state
I have a bizarro issue which I just ran into ... when passed an array of objects, the for..of iterator has no problem iterating over the objects and giving me the "name" property of each. However, array.forEach completely fails to iterate.
The main function is found in Database.ts:
import { ITableDefinition } from "./Table";
export function Database(...tables: ITableDefinition<any>[]) {
const names: string[] = [];
for (const table of tables) {
names.push(table.name);
}
return {
tables,
tableNames: tables.forEach((table) => table.name),
tableNamesWithForOf: names,
};
}
As you can see the function reflexively passes the array of tables it receives but also passes the name property of each table and it does it twice. Once using forEach and once using for..of.
When running the following Jest tests, 2 of the 3 pass but the forEach test fails:
describe("Trouble with iterables => ", () => {
// db.tables is received as an array
it("tables property is an array", () => {
const db = Database(Table(Song), Table(Playlist));
expect(Array.isArray(db.tables)).toBe(true);
expect(typeof db.tables[0]).toBe("object");
});
// for..of iterates over the array correctly and extracts the "name" prop
it("for ... of returns the names of the tables correctly", () => {
const db = Database(Table(Song), Table(Playlist));
expect(db.tableNamesWithForOf).toHaveLength(2);
expect(db.tableNamesWithForOf).toContain("Song");
expect(db.tableNamesWithForOf).toContain("Playlist");
});
// shockingly, forEach doesn't iterate at all and returns `undefined`!
it("forEach returns the names of the tables correctly", () => {
const db = Database(Table(Song), Table(Playlist));
expect(db.tableNames).toHaveLength(2);
expect(db.tableNames).toContain("Song");
expect(db.tableNames).toContain("Playlist");
});
});
My mind is blown but I'd love to hear from you if you can make some sense of it.
Git Repo - all code and tests
GitPod Container ... new to GitPod, hopefully the link works (super convenient)
Note: I tagged as both javascript and typescript but i doubt this has to with transpiling so if folks think I should take off the TS tag let me know and I'll do so.
forEach in tables.forEach((table) => table.name) doesn't return anything i.e. returns undefined, you can use .map instead
here the user_res is updated but not the state, and I have tried binding this function to this also. but same result :(
let user_res = usr_vote;
user_res.map((vote)=>{
if(vote.id==dat_id){
vote.status = stats
}
})
console.log("update user response:",user_res)
this.setState({user_response:user_res},()=>{
console.log("but this is not uodating : ",this.state.user_response)
});
I don't think even user_res is updating. map doesn't update the original variable. You need to assign the value of .map to something.
user_res = user_res.map((vote)=>{
if(vote.id==dat_id){
return {...vote, status: stats}
} else {return vote}
})
If you check documentation form Array.prototype.map(), you will see that map doesn't modify the original array, it returns a new array with the modified items.
The map() method creates a new array with the results of calling a
provided function on every element in the calling array.
So with that information you can modify your code accordingly,
// create a new array with the modified items
let user_res = usr_vote.map((vote) => {
if(vote.id == dat_id){
vote.status = stats
}
});
// update state with the new array
this.setState({user_response:user_res},()=>{
console.log("but this is not uodating : ",this.state.user_response)
});
PS: stats is not defined anywhere in your snippet. If you are not defining it somewhere in your code that your shared snippet doesn't contain, it is OK but otherwise you need to fix that part too.
Trying to manipulate the response.data to add isLoggedin = true in the response using .map but its giving me an error of "map" is not a function.
vm.dataResponse = response.data.map(function(data){
data.isLoggedIn = false;
});
Trying to do this so I can have a data to reference whether the user is logged in or not to show (login/sign out). Or I could use $rootScopebut I thought using global is not ideal?
$rootScope.isLoggedIn = false;
then in my vm.login function the $rootScope will then be set to true, this works but when I refresh the page it goes back to false.
response.data will need to be an array in order to use .map
.map will create a new array by iterating through all the values of an existing array and returning the results of a provided callback on each member of the array, eg.
var oldArray = [1,2,3,4];
var newArray = oldArray.map(function(number){
return number * 2;
});
//newArray = [2,4,6,8]
So in your example it wouldn't work even if response.data was an array as you are not returning anything from the callback.
If response.data is an object you can just add the property direct, eg.
response.data.isLoggedIn = false;
If you could do as developer033 suggests and provide the output of a console.log of response.data that would help identify how best to handle it.
Edit:
Because you are just returning a string try:
vm.dataResponse = {username: response.data, isLoggedIn: true}