AngularJS service not consuming JSON correctly with HTTP - json

I am attempting to make a HTTP request to a WebAPI using a AngularJS service and load a HTML page with two nested ng-repeat's (posts and replies). I can get the {{ post.displayName }} to populate in my browser, but replies aren't loading. Can anyone assist?
the JSON from the WebAPI:
[{"postId":1,"displayName":"Scott","message":"message1","replies":{"replyId":1,"displayName":"wayne","message":"test11"}},{"postId":2,"displayName":"Bill","message":"message12","replies":{"replyId":1,"displayName":"bob","message":"test21"}},{"postId":3,"displayName":"Wayne","message":"message12","replies":{"replyId":1,"displayName":"bob","message":"test21"}},{"postId":4,"displayName":"Bonnie","message":"message12","replies":{"replyId":1,"displayName":"bob","message":"test21"}},{"postId":5,"displayName":"Gina","message":"message12","replies":{"replyId":1,"displayName":"bob","message":"test21"}}]
My Service:
// This handles the database work for posting
gwApp.service('postService', function ($http, $q) {
// ---
// PUBLIC METHODS.
// ---
this.getPosts = function () {
var request = $http({
method: "get",
url: "http://localhost:59327/posts/details",
params: {
action: "get"
}
});
return (request.then(handleSuccess, handleError));
};
// ---
// PRIVATE METHODS.
// ---
// Transform the error response, unwrapping the application dta from
// the API response payload.
function handleError(response) {
// The API response from the server should be returned in a
// nomralized format. However, if the request was not handled by the
// server (or what not handles properly - ex. server error), then we
// may have to normalize it on our end, as best we can.
if (
!angular.isObject(response.data) ||
!response.data.message
) {
return ($q.reject("An unknown error occurred."));
}
// Otherwise, use expected error message.
return ($q.reject(response.data.message));
}
// Transform the successful response, unwrapping the application data
// from the API response payload.
function handleSuccess(response) {
return (response.data);
}
});
My Controller:
//This controller retrieves data from the services and associates then with the $scope
//The $scope is ultimately bound to the posts view
gwApp.controller('PostController', function ($scope, postService) {
$scope.posts = [];
loadRemoteData();
// public methods
// private methods
function applyRemoteData(newPosts) {
$scope.posts = newPosts;
}
function loadRemoteData() {
// $scope.posts = postService.getPosts();
postService.getPosts()
.then(
function (posts) {
applyRemoteData(posts);
}
);
}
});
My HTML code snippet:
this returns 3 blank table rows
<tr data-ng-repeat="reply in post.replies">
<td>
{{ reply.message }}
</td>
</tr>
This returns the valid data from my JSON:
<tr data-ng-repeat="post in posts">
<td>
PostId: {{ post.postId }} {{ post.displayName }}
</td>
</tr>
Any help would be much appreciated!

PLease see here: http://plnkr.co/edit/pMeopZwm2ZybIXvTRucy?p=preview
Your each post has only one object called replies, more likely that should be array of replays so you can access it like below :
<table>
<tr data-ng-repeat="post in posts">
<td>
PostId: {{ post.postId }} {{ post.displayName }}
<ul>
<li>{{post.replies.displayName}}: {{post.replies.message }}</li>
</ul>
</td>
</tr>
</table>

The answer by sss did work initially, but I got the best result when updating my JSON to use a list for the replies:
[{"postId":1,"displayName":"Scott","message":"message1","replies":[{"replyId":1,"displayName":"wayne","message":"test111"},{"replyId":2,"displayName":"bob","message":"test112"},{"replyId":3,"displayName":"bon","message":"test113"},{"replyId":4,"displayName":"ethan","message":"test114"}]},{"postId":2,"displayName":"Bill","message":"message12","replies":[{"replyId":1,"displayName":"wayne","message":"test211"},{"replyId":2,"displayName":"bob","message":"test212"}]},{"postId":3,"displayName":"Wayne","message":"message12","replies":[{"replyId":1,"displayName":"wayne","message":"test311"},{"replyId":2,"displayName":"bob","message":"test312"},{"replyId":3,"displayName":"bon","message":"test313"}]},{"postId":4,"displayName":"Bonnie","message":"message12","replies":[{"replyId":1,"displayName":"wayne","message":"test411"},{"replyId":2,"displayName":"bob","message":"test412"},{"replyId":3,"displayName":"bon","message":"test413"},{"replyId":3,"displayName":"bon","message":"test414"},{"replyId":4,"displayName":"ethan","message":"test415"}]},{"postId":5,"displayName":"Gina","message":"message12","replies":[{"replyId":1,"displayName":"wayne","message":"test511"},{"replyId":2,"displayName":"bob","message":"test512"},{"replyId":3,"displayName":"bon","message":"test513"},{"replyId":4,"displayName":"ethan","message":"test514"}]}]

Related

Can't identify elements after ajax insert

There is a data in Django DB, when html page loaded it sends request to db and create html block in Django template, and at last it insert to html by id. This part works, checkboxes creates and all is good, but there is no elements if I try to find them by id after ajax insert.
How to to get access them?
html:
<div id="fill-statuses" status-table-url="{% url 'ajax_status_data' %}"></div>
Django template:
{% for status in statuses %}
<label class="toggle">
<input class="toggle__input" type="checkbox" id="{{ status.status_new }}_status_check_box">
<span class="toggle__label">
<span class="toggle__text">{{ status.status_new }}</span>
</span>
</label>
{% endfor %}
view.py:
def fill_status_check_boxes(request):
statuses = TaskStatus.objects.values('status_new').distinct
return render(request, 'persons/statuses_for_filter.html', {'statuses': statuses})
And now js block, with comments:
function fill_status_check_boxes() {
const url = $("#fill-statuses").attr('status-table-url')
$.ajax({
url: url,
success: function (data) {
$('#fill-statuses').html(data)
},
complete: function () {
console.log(document.querySelectorAll("[id*='status_check_box']")) //return array with elements, that's why I thought that all works, when tested it
}
})
console.log(document.querySelectorAll("[id*='status_check_box']")) //but here return empty array []
}
fill_status_check_boxes()
console.log(document.querySelectorAll("[id*='status_check_box']")) //and here also return empty array []
$.ajax() is executed asynchronously
So that's why your console.log inside the complete callback display what you're expecting, instead of the one after the ajax call.
You can create a new function to call on complete :
function fill_status_check_boxes() {
const url = $("#fill-statuses").attr('status-table-url')
$.ajax({
url: url,
success: function (data) {
$('#fill-statuses').html(data)
},
complete: handleComplete
})
}
fill_status_check_boxes()
function handleComplete() {
// Do some stuffs
console.log(document.querySelectorAll("[id*='status_check_box']"))
}

Angular: How to get async data for template

I have the following problem:
I want to make a table with entries (Obj). And some of them have a file attribute.
If they have a file attribute (entry.file) I want to make a backend call to get the url of that file:
public getFileURL(archiveID: string, documentID: string, sysID: string){
const request: FileRequest = {
archiveID: archiveID,
documentID: documentID,
sysID: sysID
};
this.fileService.file(request).subscribe(response => {
if (response) {
return response;
}
})
}
This is called like: getFileURL(entry.file.archiveID, entry.file.documentID, entry.file.sysID)
And it should return an Observable, so I can check if i got a backend response.
<tr *ngFor="let entry of period.claims; let i = index">
...
<td>
<div *ngIf="entry.file">
<div *ngIf="fileClientService.getFileURL(entry.file.archiveID, entry.file.documentID, entry.file.sysID) | async as file; else loading">
<a target="about:blank" class="download" (click)="clickLink(file)"></a>
</div>
<ng-template #loading let-file>loading..</ng-template>
</div>
</td>
All I want is to display "loading" until the url is loaded and then display the a-tag.
Also, the url parameter coming back from the backend could be empty. So i also need to display nothing if the url is empty ("").
At the moment it fires hundred of backend calls for 2 objects with the entry.file property :(
I am not that good with Observables and I hope someone can help me with that.
Thank you so far :)
You need to return Observable directly from your method and map your period.claims into one Observable:
// add proper type
entries: Observable<...> = getEntries();
getEntries() {
// we map every claim to Observable returned from getFileURL method
const entries = period.claims.map(entry =>
getFileURL(...).pipe(
// we use map to return whole entry from Observable - not only url
map(url => ({
...entry,
url,
}))
));
// forkJoin will return one Observable with value array when each Observable is completed
return forkJoin(...entries);
}
public getFileURL(archiveID: string, documentID: string, sysID: string): Observable<...> {
const request: FileRequest = {
archiveID: archiveID,
documentID: documentID,
sysID: sysID
};
return this.fileService.file(request).pipe(filter(Boolean));
}
If you want not to pass to template empty response you could use filter operator and pass Boolean as callback. It will return only truthy values. You can read more about it: https://www.learnrxjs.io/learn-rxjs/operators/filtering/filter
You can read also more about forkJoin: https://www.learnrxjs.io/learn-rxjs/operators/combination/forkjoin
Note that adding proper type to method would tell you what you're doing wrong ;)

Axios request get value from nested array in Vue

In a .vue file I am trying the get value from an axios get response result which is in a nested array. The code looks like the example below (without a search form for query).
<div class="results" v-if="results">
<p>{{ results }}</p>
<p>{{ result }}</p>
</div>
<script>
import axios from 'axios';
export default {
name: 'search',
data () {
return {
query '',
results: '',
result: ''
}
},
methods: {
getResults(query) {
axios.get('https://apiexample.com/api/search.php?t_id=' + query).then( response => {
this.results = response.data.items;
this.result = response.data.items[0]['1:B'];
});
}
}
}
So for this.results I get something similar to
[{"1:A":10,"1:B":20,"1:C":30,"1:D":40,"1:E":50},
{"1:A":20,"1:B":30,"1:C":40,"1:D":50,"1:E":60},
{"1:A":30,"1:B":40,"1:C":50,"1:D":60,"1:E":70},
{"1:A":40,"1:B":50,"1:C":60,"1:D":70,"1:E":80}]
For this.result I am getting undefined when I am trying to get the value of 20. Probably navigating that type of response incorrectly or perhaps something more specific needs to be added to data() {}?
Any help would be appreciated.
Thanks.
As noted in the comments, response.data.items is a string, not an object. This seems like a flawed API response, with the items unnecessarily encoded as a JSON string within the response.
However, assuming that fixing the problem in the server is not possible, the items can be decoded in the UI:
this.results = JSON.parse(response.data.items);
this.result = this.results[0]['1:B'];

NodeJS - Return a JSON from a request

I am currently doing some stuffs in NodeJS and now I have the following issue:
When I get a JSON Object from a HTTP Request and want to return it, it's showing "undefined".
Here is my not working NodeJS Code:
function verifyUser(uname,pword){
var options = {
url: 'CENSORED',
method: 'POST',
headers: headers,
form: {'Username':uname, 'Password':pword, 'Key':key}
}
request(options,function(error,response,body){
if(!error && response.statusCode == 200){
return body;
}
})
}
var test1 = verifyUser("RobDeFlop","CENSORED");
console.log(test1);
But when I replace the return with a console.log its showing me the json object.
I hope someone can help me :)
Ah, the joys of learning async js in node for the first time :3
As #Mark_M mentioned, your function in request is only called after the request is processed. As a result, you can't return a variable from your verifyUser() function. verifyUser() returns immediately once it has SENT the request, and calls the funciton in request() once it has received an answer.
Ideally, you should follow the async flow by providing a callback function:
//We'll define some function called 'callback'
function verifyUser(uname,pword, callback){
var options = {
url: 'CENSORED',
method: 'POST',
headers: headers,
form: {'Username':uname, 'Password':pword, 'Key':key}
}
request(options,callback);
// Here I've changed your inline callback function to the one passed to verifyUser as an argument.
}
// Then, your main code:
verifyuser("RobDeFlop","CENSORED", next);
function next(error,response,body){
if(!error && response.statusCode == 200){
//Do useful stuff with the body here.
}
})
}

Angularjs - show values from a server request

I got this json data back from the server: {"start":"29-11-2014","end":"31-12-2014","pris":"372.27"}
In my .success i have $scope.paymentInfo = data; then i try to output it in my html view like this
{{ paymentInfo.start }}
but it does not work but if i try {{ paymentInfo }} it shows the json object, what do i have to do, to get the start, end etc. ?
$scope.selectMembership = function(values){
//console.log(values);
centerSettings.getPriceForPeriod(values)
.success(function(data) {
console.log(data);
$scope.paymentInfo = data;
})
.error(function(data) {
console.log('fejl ved hentning af centre');
console.log(data);
});
};
I think you need to deserialize the string to Json object.
Try using $scope.paymentInfo = angular.fromJson(data);