I have successfully retrieved the JSON data but I don't seem to find a way to output the value as I would be able to for others. Wonder what went wrong in the way to display the value in my template?
The function is as follows,
getUserInfo() {
var service = this;
let url = service.appConfig.Shop_URL + "/wp-json/wp/v2/users/" + service.userService.id;
url = this.initUrl(url, '');
var headers = new Headers();
headers.append('Authorization', 'Bearer ' + service.userService.token);
headers.append('Content-Type', 'application/json');
return new Promise(function (resolve, reject) {
service.http.get(url, { headers: headers }).pipe(map(res => res.json())).subscribe(data => {
if (data) {
service.cachedData = data;
console.log(data);
resolve(service.cachedData);
}
else {
reject();
}
});
});
}
listUserDetails() {
this.getUserInfo().then((data: Array<any>) => {
this.user_details = data;
console.log(this.user_details);
});
}
In the console the data shows as follows,
{id: 584, name: "test", url: "", description: "", link: "https://oc.xxxxx.com/author/test/", …}
avatar_urls: {24: "https://secure.gravatar.com/avatar/b642b4xxx", 48: "https://secure.gravatar.com/avatar/b642b4xxx", 96: "https://secure.gravatar.com/avatar/b642bxxxx"}
commission_earned: "36"
commission_rate: "5"
daily_sales: "720"
description: ""
id: 584
link: "https://oc.xxxxx.com/author/test/"
meta: []
name: "test"
slug: "test"
url: ""
And in my template I used the following method but it is not returning the values.
<span *ngFor="let detail of user_details">{{detail.daily_sales}}</span>
thanks in advance.
You proberly just need to handle the user_details like an object not an array
so change
<span *ngFor="let detail of user_details">{{detail.daily_sales}}</span>
to
<span >{{user_details.daily_sales}}</span>
More info on *ngFor here : https://angular.io/api/common/NgForOf
Related
I am trying to query the database based on what the user has clicked on the page and display the data retrieved by it without refreshing the page. I am using Ajax for this. Let me show you the codes
html
<label for="landacq" class="civil-label">Land Acquisation Cases</label>
<input class="civil-category" type="radio" name="civil-cat" id="landacq" value="land acquisation" hidden>
<label for="sc" class="civil-label">Supreme Court</label>
<input class="civil-court" type="radio" name="civil-court" id="sc" value="supreme court" hidden>
<label for="limitation" class="civil-label">Limitation</label>
<input class="civil-law-type" type="radio" name="civil-law-type" id="limitation" value="limitation" hidden>
js
for (i = 0; i < lawTypeInput.length; i++) {
lawTypeInput[i].addEventListener("click", (e) => {
e.preventDefault();
cat = civilCatval;
court = civilCourtval;
lawT = civillawTypeval;
console.log("this is from ajax : ", cat, court, lawT);
$.ajax({
type: "POST",
headers: { "X-CSRFToken": csrftoken },
mode: "same-origin", // Do not send CSRF token to another domain.
url: "civil",
data: {
"cat[]": civilCatval,
"court[]": civilCourtval,
"lawT[]": civillawTypeval,
},
success: function (query) {
showCivilQ(query);
// console.log(data);
},
error: function (error) {
console.log(error);
},
});
});
}
function showCivilQ(query) {
q.textContent = query;
console.log(query);
}
So here for example, if the user the click the radio button in the html, the values are grabbed by in js file and then sent to the url mentioned as a POST request. There these values are use to filter the database and return the objects like this
views.py
def civil_home(request):
if request.is_ajax():
get_cat = request.POST.get('cat[]')
get_court = request.POST.get('court[]')
get_lawT = request.POST.get('lawT[]')
query = Citation.objects.filter(law_type__contains ='civil' ,sub_law_type__contains= get_cat, court_name__contains = get_court, law_category__contains = get_lawT)
return HttpResponse(query)
else:
subuser = request.user
subscription = UserSubscription.objects.filter(user = subuser, is_active = True)
context = {
'usersub': subscription,
}
return render(request, 'civil/civil_home.html', context)
This is the result I am getting which is correct.
My Question is these objects contain attributes having some values in for eg, title, headnote etc. How can I display these attributes in the html rather than displaying the object names returned as shown in the Image like title of the citation, headnote of the citation etc
A solution could be to return a json object instead of the query resultset; because Ajax works well with json
You need a function that translates a Citation object into a dictionary (change it based on your real attributes). All elements must be translated into strings (see date example)
def citation_as_dict(item):
return {
"attribute1": item.attribute1,
"attribute2": item.attribute2,
"date1": item.date.strftime('%d/%m/%Y')
}
This dictionary must be translated into a json through import json package
def civil_home(request):
if request.is_ajax():
get_cat = request.POST.get('cat[]')
get_court = request.POST.get('court[]')
get_lawT = request.POST.get('lawT[]')
query = Citation.objects.filter(law_type__contains ='civil' ,sub_law_type__contains= get_cat, court_name__contains = get_court, law_category__contains = get_lawT)
response_dict = [citation_as_dict(obj) for obj in query]
response_json = json.dumps({"data": response_dict})
return HttpResponse(response_json, content_type='application/json')
else:
subuser = request.user
subscription = UserSubscription.objects.filter(user = subuser, is_active = True)
context = {
'usersub': subscription,
}
return render(request, 'civil/civil_home.html', context)
In your HTML page you should be able to parse the response as a normal JSON object
I figured out another way to do it, which is giving me the required results too.
Here I am filtering the values of the query, and then converting it to a list and passing it as a JsonResponse
views.py
def civil_home(request):
if request.method == "POST" and request.is_ajax():
get_cat = request.POST.get('cat[]')
get_court = request.POST.get('court[]')
get_lawT = request.POST.get('lawT[]')
query = Citation.objects.values().filter(law_type__contains ='civil' ,sub_law_type__contains= get_cat, court_name__contains = get_court, law_category__contains = get_lawT)
result = list(query)
return JsonResponse({"status": "success", "result": result})
else:
subuser = request.user
subscription = UserSubscription.objects.filter(user = subuser, is_active = True)
context = {
'usersub': subscription,
}
return render(request, 'civil/civil_home.html', context)
And then I am recieving the reponse here and iterrating over it to print the attributes in the html
js
for (i = 0; i < lawTypeInput.length; i++) {
lawTypeInput[i].addEventListener("click", (e) => {
e.preventDefault();
cat = civilCatval;
court = civilCourtval;
lawT = civillawTypeval;
console.log("this is from ajax : ", cat, court, lawT);
$.ajax({
type: "POST",
headers: { "X-CSRFToken": csrftoken },
mode: "same-origin", // Do not send CSRF token to another domain.
url: "civil",
data: {
"cat[]": civilCatval,
"court[]": civilCourtval,
"lawT[]": civillawTypeval,
},
success: function (response) {
console.log(response.result);
civilData = response.result;
if ((response.status = "success")) {
$("#queryResult").empty();
for (i = 0; i < civilData.length; i++) {
$("#queryResult").append(
`
${civilData[i].title}
<p>${civilData[i].headnote}</p>
`
);
}
} else {
$("#queryResult").empty();
$("#queryResult").append(
`
<p>No Citations Found</p>
`
);
}
},
error: function (error) {
console.log(error);
},
});
});
}
A csrf_token can be mentioned at the top of the html page and then it can be passed in the header to avoid any conflict.
I have a button which depending on whether the text input it triggers is opened or not, switches between 'Report A Problem' to 'Close'. In an effort to consolidate my code I've decided to use Handlebars.JS to create the following:
<button id="myBtnToReportABug" onclick="toggleReportForm(); clearFields();" type="button" class="btn btn-secondary float-right" >{{#if report_form_opened}} Report A Problem {{else}} Close {{/if}}</button>
I've followed examples in the documentation, and as you can see in the Javascript I will attach below, I have a functioning toggle on togggleReportForm, which console logs true & false upon each click. I'm not sure what I'm missing here and would appreciate any tips.
Currently the button only displays 'Close' with no error messages.
var report_form_opened = report_form_opened;
$(document).ready(function() {
const client = ZAFClient.init();
$("#myBtnToReportABug").click(() => collapse.collapse('toggle'));
$("#bugForm").submit((e) => {
e.preventDefault()
const input = document.getElementById('nameInput');
bugInfo = {
"name": "Report From " + idTicket,
"story_type" : "Bug",
"description": input.value + " " + `${data.ticket.brand.url}/agent/tickets/${idTicket}`,
}
reportBug(bugInfo).then(collapse.collapse('toggle'))
})
});
});
});
async function reportBug(data = {}) {
const url = 'https://www.pivotaltracker.com/services/v5/projects/2530461/stories'
const response = await fetch(url, {
method: 'POST',
headers: {
"X-TrackerToken": `${metadata.settings.token}`,
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
return response.json();
}
// changes text on 'report problem' button when form open
function toggleReportForm() {
report_form_opened = !report_form_opened;
console.log(toggleReportForm)
}
// clears text field onclick
function clearFields() {
document.getElementById("nameInput").value = "";
}
My vue.js code is unable to access a reference in a returned json object.
The vue.js code
new Vue({
el: '#axios',
data: function() {
return {
bikes: null,
baseurl: "https://" + document.querySelector('#axios').dataset.hostportname + "/",
}
},
mounted () {
axios({
method: 'get',
url: 'api/v1/bicycles',
baseURL: this.baseurl
})
.then(response => {
this.bikes = response.data
console.log("now bikes are " + JSON.stringify(this.bikes[0].owner.userName));
})
.catch(error => console.log("There is an error getting bikes: " + error))
}
})
If the HTML file (just a part) is
<div id="axios" th:data-hostportname="${hostportname}">
<li v-for="bike in bikes" :key="bike.id">
{{ bike.make }} ------- {{ bike.owner }}
</li>
</div>
Then the html output is
dawes -------- { "id": 1, "userName": "user1"}
whyte -------- { "id": 2, "userName": "user2"}
whyte -------- { "id": 3, "userName": "user3"}
And the console.log output is
now bikes are "user1"
if I try to output the owner id alone
<div id="axios" th:data-hostportname="${hostportname}">
<li v-for="bike in bikes" :key="bike.id">
{{ bike.make }} ------ {{ bike.owner.id }}
</li>
</div>
no output with a console error of
TypeError: "bike.owner is undefined"
So the Axios code is returning the correct data. Each object in the array is accessible. But the nested object within each array member is not accessible at a field level.
Just to make clear, if I ask for {{ bike.owner }} then I get a displayed the oener record that is referenced by the bike record. If I ask for {{ bile.owner.id }} then I get the console.log error of bike.owner is undefined and nothing is displayed. So I don't see how this is a loading problem unless bike.owner.id takes longer to retrieve than bike.owner, even though the latter displays.
Can someone explain what I am misunderstanding?
Regards.
So I found the root cause and it had nothing to do with vue.
Basically I have two models - owners and bicycles. Bicycles have a ref to a single owner. And owners have ref to an array of bicycles. I added #JsonIdentityInfo to both. And that was my problem.
Changing this to having #JsonIdentityInfo only in owner then allowed it to work.
Many thanks for all of the suggestions.
I think the response you are getting is as follows where owner is also a string.
So you might have to parse it before assigning it to bikes.
[{
make: 'one',
owner: '{ "id": 1, "userName": "user1"}'
}, {
make: 'two',
owner: '{ "id": 2, "userName": "user2"}'
}, {
make: 'three',
owner: '{ "id": 3, "userName": "user2"}'
}]
Hope this helps.
Update 1
Can you try adding a loading flag?
https://v2.vuejs.org/v2/cookbook/using-axios-to-consume-apis.html
new Vue({
el: '#axios',
data: function() {
return {
bikes: null,
loading: true
baseurl: "https://" + document.querySelector('#axios').dataset.hostportname + "/",
}
},
mounted () {
axios({
method: 'get',
url: 'api/v1/bicycles',
baseURL: this.baseurl
})
.then(response => {
this.bikes = response.data
console.log("now bikes are " + JSON.stringify(this.bikes[0].owner.userName));
})
.catch(error => console.log("There is an error getting bikes: " + error)).finally(() => this.loading = false)
}
})
And add v-if to your block
<div id="axios" v-if="!loading" th:data-hostportname="${hostportname}">
<li v-for="bike in bikes" :key="bike.id">
{{ bike.make }} ------ {{ bike.owner.id }}
</li>
</div>
Hey having a issue with the rendering of a .erb file, in my AJAX call I make a call to my create action on rails where I validate and process the form data and sent back the completed order data as render: json which works fine.
I have a conditional that checks to see if parameter exists, it if does then the completed order data is passed back as a response via render: json
It if doesn't exists it will render a receipt page.
The problem is when I render the receipt page, the full HTML receipt page comes back as a response instead of rendering the page. Please Help!
$scope.placeOrder = function() {
var body = composeOrderBody();
var isValid = validateForm(body.order);
if(isValid) {
var orderComplete = '<%= #orderComplete %>';
var baseUrl = '<%= request.base_url %>';
console.log('Passing order object: ', body.order);
$http({
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
url: checkout_url,
data: {
order: body.order,
xhr_request: true
},
}).then((function(_this) {
return function(response) {
if(typeof response.data == 'undefined' || response.data == null || !response.data) {
console.log('Error: missing Order Number from Order Confirmation data.', response.data);
}
console.log('Order Confirmation response data object:' , response.data);
if(orderComplete) {
var redirectUrl = 'http://' + orderComplete
var order_params = `?oid=${response.data.oid}?cart=${response.data.cart}?total=${response.data.total}`
window.location.href = redirectUrl + order_params;
} else {
console.log('Base Url: ', baseUrl);
// window.location.href = `${baseUrl}/receipt`;
}
};
})(this));
} else {
console.log('Form Validation or Stripe Validation Failed');
}
} // end placeOrder
Rails Code
# Redirect to orderComplete URL if it's set
if !#orderComplete.blank?
puts 'orderComplete parameter is not blank'
# Sum up all the line item quantities
qty = #order.line_items.inject(0) {|sum, line_item| sum + line_item.quantity}
# Get all of the coupons (and values) into a string
coupons = #order.applied_coupons.map { |coupon| coupon.coupon }.join(',')
coupon_values = #order.applied_coupons.map { |coupon| '%.2f' % coupon.applied_value.to_f }.join(',')
order_params = {
"oid" => URI::escape(#order.number),
"cart" => URI::escape(#cart),
"total" => URI::escape('%.2f' % #order.total),
}
#redirectUrl = URI.parse(URI.escape(#orderComplete))
#redirectUrl.query = [#redirectUrl.query, order_params.to_query].compact.join('&')
#redirectUrl = #redirectUrl.to_s
if params[:xhr_request]
render json: order_params.to_json
return
end
render 'receipt_redirect', :layout => 'receipt_redirect'
else
puts 'OrderComplete Parameter is blank'
render 'receipt', :layout => 'receipt', :campaign => #campaign
end
i am trying to get unique values for a nested ng-repeat
there are the two scopes i am working with
$scope.AllGames = [
{ title: "Doom", productCode: "458544", id_product: "1" },
{ title: "Wolvenstein", productCode: "457104", id_product: "2" },
{ title: "Quake", productCode: "32542687", id_product: "3" }
];
$scope.AllPrices= [
{ id_productPrice: "1", id_product: "1", price : "599" },
{ id_productPrice: "2", id_product: "1", price : "699" },
{ id_productPrice: "3", id_product: "2", price : "249" }
];
this is the html
<div ng-repeat="game in AllGames">
<div>{{game.title}} | {{game.id_product}} | {{game.title}}</div>
<div ng-init="getPriceByGame(game.id_product)">
<div ng-repeat="item in AllPrices">
{{item.price}}
</div>
</div>
and this is the controller
$scope.getAllGames = function () {
var request = 'Games';
$http({
method: 'Get',
url: uri + request
})
.success(function (data) {
$scope.AllGames = data;
})
}
$scope.getPriceByGame = function (id_product) {
var request = AllPrices/' + id_product;
$http({
method: 'Get',
url: uri + request
})
.success(function (data) {
$scope.AllPrices = data;
})
};
So the idea is that i send the id_product to the database and i get a list of prices back for that id, i would like to connect these prices for each unique product. what happens now is that the ng-init works fine and the request gets send with the id, i receive the prices for that id. In the console log i see all the prices coming in by product_id (all different arrays) but i can't seem to connect them in the html so i actually see the prices.
The last request overwrites of course all the prices for each game in the ng-repeat. How do i keep this unique? So that each product gets the prices for that id.
You could place another ng repeat to loop through the all Prices array. Every time you get new data, you push it to the array.
Don't forget to make an edit in the nested ng repeat of all prices, it should loop only through the current index