I am working on Angular 6 and i want to post an array of JSON objects using a service class.
The following is my function
getrerun(data,file){
this.post=[];
for(var i=0;i<data.length;i++)
{
this.rerun.storeno=data[i].storeNo;
this.rerun.filetype=data[i].loadtype;
this.rerun.outboundsystem[0]=file;
this.rerun.createdate=data[i].createdDate;
this.post[i]=this.rerun;
console.log("------>"+JSON.stringify(this.rerun)+"------->"+JSON.stringify(this.post));
}
this.newurl=this.devurl+"rerun";
return this.http.post<any>(this.newurl,this.post);
}
newurl is the url of the rest api that i want to hit and this.post is the array that i am sending
The value of data is following:
[{"lastDate":"2019-02-20 12:36:27","storeNo":"G015","country":"SG","serviceStatus":"FAIL","createdDate":"2019-01-04 11:53:56","loadtype":"F"},{"lastDate":"2019-02-20 10:54:00","storeNo":"G121","country":"SG","serviceStatus":"FAIL","createdDate":"2019-01-23 16:29:33","loadtype":"F"}]
and file is 'TP';
However the post array that I am getting is this:
[{"outboundsystem":["TP"],"storeno":"G121","filetype":"F","createdate":"2019-01-23 16:29:33"},{"outboundsystem":["TP"],"storeno":"G121","filetype":"F","createdate":"2019-01-23 16:29:33"}]
this basically means that both the entries in the array are the same i.e this.post[0].storeno is same as this.post[1].storeno. However, they should have two different values.
What do I do about this?
Hi I am updating a json object which has internal array and each object of array has id element. Based on id element I update one of the element which matches the inout id, but it is modifying more than one object. My source code and console logs are given below which will help in understanding the issue.
function
updateUserData(event,id){
var elementName=event.target.name;
console.log('id='+id+', element name='+elementName);
var userData=this.state.user_data;
console.log('User Data before change ='+JSON.stringify(userData));
for(var i=0;i<userData.sports.length;i++){
for(var j=0; j<userData.sports[i].ticket_detail.length;j++){
if(userData.sports[i].ticket_detail[j].id==id){
for(var k=0;k<userData.sports[i].ticket_detail[j].ticket.length;k++){
if(userData.sports[i].ticket_detail[j].ticket[k].paramname==event.target.name){
userData.sports[i].ticket_detail[j].ticket[k].value=event.target.value;
console.log('user data after change ='+JSON.stringify(userData));
this.setState({user_data:userData});
return;
}
}
}
}
}
}
console logs
value=h
id=0, element name=name
User Data before change =
{"total_tickets":3,"total_amount":2124,"htmlid_counter":3,"sports":[{"name":"Badminton","ticket_detail":[{"cat":"Men Singles","formid":102,"ticket":[{"label":"Name:","paramname":"name","type":"text","value":""},{"label":"Email:","paramname":"email","type":"text","value":""},{"label":"Phone:","paramname":"phone","type":"text","value":""}],"id":0},{"cat":"Men
Singles","formid":102,"ticket":[{"label":"Name:","paramname":"name","type":"text","value":""},{"label":"Email:","paramname":"email","type":"text","value":""},{"label":"Phone:","paramname":"phone","type":"text","value":""}],"id":1},{"cat":"Men
Singles","formid":102,"ticket":[{"label":"Name:","paramname":"name","type":"text","value":""},{"label":"Email:","paramname":"email","type":"text","value":""},{"label":"Phone:","paramname":"phone","type":"text","value":""}],"id":2}]},{"name":"Carrom","ticket_detail":[]}],"tournament_id":1}
user data after change =
{"total_tickets":3,"total_amount":2124,"htmlid_counter":3,"sports":[{"name":"Badminton","ticket_detail":[{"cat":"Men Singles","formid":102,"ticket":[{"label":"Name:","paramname":"name","type":"text","value":"h"},{"label":"Email:","paramname":"email","type":"text","value":""},{"label":"Phone:","paramname":"phone","type":"text","value":""}],"id":0},{"cat":"Men
Singles","formid":102,"ticket":[{"label":"Name:","paramname":"name","type":"text","value":"h"},{"label":"Email:","paramname":"email","type":"text","value":""},{"label":"Phone:","paramname":"phone","type":"text","value":""}],"id":1},{"cat":"Men
Singles","formid":102,"ticket":[{"label":"Name:","paramname":"name","type":"text","value":"h"},{"label":"Email:","paramname":"email","type":"text","value":""},{"label":"Phone:","paramname":"phone","type":"text","value":""}],"id":2}]},{"name":"Carrom","ticket_detail":[]}],"tournament_id":1}
You can see from the abobe json , even though input id=0, but json object with id 0 , 1 and 2 are modified. Can someone help me to resolve this issue.
You are doing a asynchronous setState at each iterations. that's probably why you are getting a weird result.
You have to build a new array, then, after your array is what you finally want in your state, you can do:
this.setState({ user_data: newArray })
I found the issue. This issue was happening because each element of array was havinv reference to a common element. That was the reason when I was modifying any one of them, all were been modified.
Application
A simple Search bar and a button where user enters a keyword and the response returned is from a RESTful server (HTTP GET requests)
simplesearch.ts
export class SimpleSearch {
kw: string; // keyword
resp: string; // response from Server
}
simplesearch.service.ts
Has a simple method called searchData which does a HTTP GET request with the user's keyword as a query search. (Code not included for brevity)
simplesearch.component.ts
/*All respective headers and #Component removed from brevity*/
const OUTPUT: SimpleSearch[] = []; // create an array for storing Objects
export class SimpleSearchComponent {
Output = OUTPUT; // define variable for array
constructor(private httpServ: SimpleSearchService, private temp: SimpleSearch) {}
/*Search button on HTML file does this*/
Search(inputVal: string) {
this.temp.kw = inputVal; // store the value of user's input
this.httpServ.searchData(inputVal)
.then(res => this.temp.resp = res); // store the response in temp.resp
// push the Object on the Output Array
this.Output.push({kw: this.temp.kw, resp: this.temp.resp});
}
}
Interpolation Variable
I use Output as an Interpolation Variable for my HTML template. I show the data in an unordered list
<ul>
<li *ngFor="let keyword of Output">
<span>{{keyword.kw}}</span>
</li>
</ul>
Response:
<ul>
<li *ngFor="let answer of Output">
<span>{{answer.resp}}</span> <!-- WHAT TO DO HERE for Array Index-->
</li>
</ul>
Result
I can see the keywords in a list every time a user inputs new keywords but
the responses in the wrong way
How do I pass Indexing with the Interpolation? Or am I thinking wrong?
The easy way out was to create two separate Array<String> for keywords and responses and this works great since I can use the index to delete the contents on the page too but with an Object in an Array I am confused with the key: value representation and the index of the Array (OUTPUT) itself.
The problem lies exactly where developer noticed, this.temp.resp is outside the async function. So when you are pushing items in your Output array, it's always pushing the previous search with the new keyword, therefore you are getting the behavior that the resp is always "one step behind". You can check this to understand this async behavior: How do I return the response from an Observable/http/async call in angular2?
So let's look at the code and explain what is happening. I assume you have initialized 'temp' since it isn't throwing an error on first search, where temp.resp would be undefined unless temp is initialized.
this.httpServ.searchData(inputVal)
// this takes some time to execute, so the code below this is executed before 'this.temp.resp' has received a (new) value.
.then(res => this.temp.resp = res);
// old value of 'temp.resp' will be pushed, or if it's a first search, empty value will be pushed
this.Output.push({kw: this.temp.kw, resp: this.temp.resp});
So how to solve this, would be to move the this.Output.push(... line inside the callback (then), so that the correct values will be pushed to the array.
Also I'd change your model to be an Interface instead of Class. But as to how to change the function and do the assignment inside the callback, I'd also shorten the code a bit and do:
Search(inputVal: string) {
this.httpServ.searchData(inputVal)
.then(res => {
// we are pushing values inside callback now, so we have correct values!
// and 'SimpleSearch' stands for the interface
this.Output.push(<SimpleSearch>{kw: inputVal, resp: res});
});
}
}
This should take care of it that the corresponding keyword will have the corresponding response! :)
PS. Worth noticing here, is that you'd maybe want to display the keyword while we are waiting for the response for that keyword, I ignored it here though and applied the same as you are currently using.
I have the following ids:
var myIds = ['somelongId', 'someotherlongid'];
I want to get only the records that correspond from mongo (I am using angular-fullstack) using $resource.
My factory
angular.module('myApp')
.factory('MyFactory',function ($resource) {
return $resource('/api/things/:id');
});
My faulty code returns all the records
MyFactory.query(myIds);
You should query correctly, by passing id parameter in it. You can't pass array object inside query, if you try to pass that then that will make stringify that array to [Object Object] & it will throw an error.
Instead I'd suggest you to pass any one of id to it.
MyFactory.query({ id: myIds[0] });
Edit
If you wanted to pass multiple ids in a query statement then pass it as , separated string and then do split out that key on server side. In that way you could pass multiple array to server & will get array of response(.query will make thing done).
MyFactory.query({ id: myIds.join(',') });
This will create url as
http://localhost/api/things/somelongId,someotherlongid
I'm trying to extend an object in angularJs using multiple ajax calls results. However only the last results extends my empty object.
$rootScope.progress = {}; // the objkect to extend
$http.get('data.json').
then(function(result){angular.extend($rootScope.progress,result.data)}),
$http.get('error.json').
then(function(result){angular.extend($rootScope.progress,result.data)}),
$http.get('data2.json').
then(function(result){angular.extend($rootScope.progress,result.data)}),
$http.get('data3.json').
then(function(result) {angular.extend($rootScope.progress,result.data)})
You could see a plunker here:http://plnkr.co/edit/iDmsTpDpFUnvrv1pCUU9?p=preview
It is because all your data return is array instead of object.
Changed all the data.json to object.
Refer to http://plnkr.co/edit/Gq22dsksxlPYCryM1BOs?p=preview
If your json always return array, then your $scope.result should changed to array.
you can use $scope.result = $scope.result.concat(value.data);