Add JSON value to ko.computed in viewmodel - json

I am busy creating a currency Module for my web app, I am using Yahoo Finance API to return the currency conversion rate of 2 currencies that I have defined in my local DB. I get the JSON data fine from the API, I just want to Bind the JSON data that I have received from the Finance API to my existing Viewmodel using ko.computed. I am not sure if I should be using ko.computed to achieve this, so any advice will help greatly.
Here is my code:
var currency = function (data) {
var self = this;
self.CurrencyFrom = ko.observable(data.CurrencyFrom);
self.CurrencyTo = ko.observable(data.CurrencyTo);
self.ConversionRate = ko.computed(rates); // I WANT TO BIND THE VALUE FROM API HERE
}
var CurrencyModel = function (Currencies) {
var self = this;
self.Currencies = ko.observableArray(Currencies);
self.AddCurrency = function () {
self.Currencies.push({
CurrencyFrom: "",
CurrencyTo: "",
ConversionRate: ""
});
};
self.RemoveCurrency = function (Currency) {
self.Currencies.remove(Currency);
};
self.Save = function (Form) {
alert("Could Now Save: " + ko.utils.stringifyJson(self.Currencies));
};
$.ajax({
url: "CurrencyConfiguration.aspx/GetConfiguredCurrencies",
// Current Page, Method
data: '{}',
// parameter map as JSON
type: "POST",
// data has to be POSTed
contentType: "application/json; charset=utf-8",
// posting JSON content
dataType: "JSON",
// type of data is JSON (must be upper case!)
timeout: 10000,
// AJAX timeout
success: function (Result) {
var MappedCurrencies =
$.map(Result.d,
function (item) {
getRate(item.CurrencyFrom, item.CurrencyTo);
return new currency(item);
}
);
self.Currencies(MappedCurrencies);
},
error: function (xhr, status) {
alert(status + " - " + xhr.responseText);
}
});
};
//3rd Party JSON result from Yahoo Finance API
function getRate(from, to) {
var script = document.createElement('script');
script.setAttribute('src', "http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D" + from + to + "%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json&callback=rates"); //HERE I CALL THE VALUE TO OBTAIN THE CONVERSION RATE FROM API
document.body.appendChild(script);
}
//I WANT TO ADD THIS TO MY VIEWMODEL
var rates = function parseExchangeRate(YahooData) {
var rate = YahooData.query.results.row.rate;
}
$(document).ready(function () {
var VM = new CurrencyModel();
ko.applyBindings(VM);
$('[rel=tooltip]').tooltip();
})
The JSON returned from parseExchangeRate Function (Yahoo Query Result):
parseExchangeRate({"query":{"count":1,"created":"2013-01-18T06:46:41Z","lang":"en-US","results":{"row":{"rate":"0.1129","name":"ZAR to USD"}}}});

I see you're already using jquery so I'll use jquery for the JSONP too. I'm using a simple ko.observable for the conversion rate, and added a "bare" ko.computed that does the ajax request and asynchronously updates the observable. Let me know if you need any further clarification.
JSFiddle example (with mock data instead of your initial ajax): http://jsfiddle.net/VsW5H/1/
Updated code:
var currency = function (data) {
var self = this;
self.CurrencyFrom = ko.observable(data.CurrencyFrom);
self.CurrencyTo = ko.observable(data.CurrencyTo);
self.ConversionRate = ko.observable(data.ConversionRate);
ko.computed(function () {
var from = self.CurrencyFrom(),
to = self.CurrencyTo();
if (!from || !to) {
self.ConversionRate("N/A");
return;
}
getRate(from, to).done(function (YahooData) {
console.log("got yahoo data for [" + from + "," + to + "]: ", YahooData);
self.ConversionRate(YahooData.query.results.row.rate);
});
});
}
var CurrencyModel = function (Currencies) {
var self = this;
self.Currencies = ko.observableArray(Currencies);
self.AddCurrency = function () {
self.Currencies.push(new currency({
CurrencyFrom: "",
CurrencyTo: "",
ConversionRate: ""
}));
};
self.RemoveCurrency = function (Currency) {
self.Currencies.remove(Currency);
};
self.Save = function (Form) {
alert("Could Now Save: " + ko.utils.stringifyJson(self.Currencies));
};
$.ajax({
url: "CurrencyConfiguration.aspx/GetConfiguredCurrencies",
// Current Page, Method
data: '{}',
// parameter map as JSON
type: "POST",
// data has to be POSTed
contentType: "application/json; charset=utf-8",
// posting JSON content
dataType: "JSON",
// type of data is JSON (must be upper case!)
timeout: 10000,
// AJAX timeout
success: function (Result) {
var MappedCurrencies = $.map(Result.d,
function (item) {
return new currency(item);
});
self.Currencies(MappedCurrencies);
},
error: function (xhr, status) {
alert(status + " - " + xhr.responseText);
}
});
};
//3rd Party JSON result from Yahoo Finance API
function getRate(from, to) {
return $.getJSON("http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D" + from + to + "%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json&callback=?");
}

Related

Pass a parameter from client-side to server side and get result

I knows it sounds basic but I can't seem to get it right. I'm trying to get a data from the API but it needs a parameter in order to obtain the data. How can I pass the parameter and get the result which is a JSON array
$(function() {
var proxy = 'http://192.168.1.126/lms-dev-noel/proxy.php';
var endpoint = 'account/';
var rt = 'GET';
var url = proxy+'?endpoint='+endpoint+'&rt='+rt;
var param = {
'lastsyncdate' : '2016-12-06'
};
$.get(url, function(param) {
console.log('Success');
});
});
ways to achieve this :
using jQuery.ajax() method :
var proxy = 'http://192.168.1.126/lms-dev-noel/proxy.php';
var endpoint = 'account/';
var url = proxy+'?endpoint='+endpoint+'&rt='+rt;
var method = 'GET';
var params = {
'lastsyncdate' : '2016-12-06'
};
$.ajax({
url: url,
type: method, //send it through get method
data: params,
success: function(response) {
//Do Something
},
error: function(xhr) {
//Do Something to handle error
}
});
using jQuery.get() method :
var proxy = 'http://192.168.1.126/lms-dev-noel/proxy.php';
var endpoint = 'account/';
var url = proxy+'?endpoint='+endpoint+'&rt='+rt;
var method = 'GET';
var params = {
'lastsyncdate' : '2016-12-06'
};
$.get(url, params, function(res) {
console.log(res);
});
I just pass parameters as name value pairs like so...
$.get(
"yoururl.php",
{ color: "red", size: "small" }, // your params go here as name / value pairs
function(response){
console.log(response);
}
);

Select2 Load Remote Data Not working When URL Changed to Google Address Autocomplete AII

I have this Select2 working with its supplied example when loading
Github users data: https://api.github.com/search/repositories
but NOT working anymore when replace the AJAX url call to
Google Address Autocomplete:
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=Vict&types=geocode&language=fr&key=*************************
my codes:
<select class="js-data-example-ajax">
<option value="3620194" selected="selected">select2/select2</option>
</select>
<script>
function formatRepo (repo) {
if (repo.loading) return repo.text;
var markup = '<div class="clearfix">' +
'<div class="col-sm-1">' +
'<img src="' + repo.owner.avatar_url + '" style="max-width: 100%" />' +
'</div>' +
'<div clas="col-sm-10">' +
'<div class="clearfix">' +
'<div class="col-sm-6">' + repo.full_name + '</div>' +
'<div class="col-sm-3"><i class="fa fa-code-fork"></i> ' + repo.forks_count + '</div>' +
'<div class="col-sm-2"><i class="fa fa-star"></i> ' + repo.stargazers_count + '</div>' +
'</div>';
if (repo.description) {
markup += '<div>' + repo.description + '</div>';
}
markup += '</div></div>';
return markup;
}
function formatRepoSelection (repo) {
//return repo.description || repo.text;
return repo.full_name || repo.text;
}
$(document).ready(function(){
$(".js-data-example-ajax").select2({
ajax: {
url: "https://api.github.com/search/repositories",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, page) {
// parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to
// alter the remote JSON data
return {
results: data.items
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
});
</script>
the error showing is :
XMLHttpRequest cannot load https://maps.googleapis.com/maps/api/place/autocomplete/json?input=Vict&types=geocode&language=fr&key=**************************&q=v. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access.
Can someone who has integrated Google Map Api and Select2 help? I am not too sure where to troubleshoot from here now...
***I am building my app in Laravel 5
***I already tried installing barryvdh/laravel-cors, but same problem!!
Try to add $.ajaxSetup with csrf token:
before ajax call:
$.ajaxSetup({
headers: {'X-CSRF-Token': $('meta[name=_token]').attr('content')}
});
and in your head meta:
<meta name="_token" content="{{ csrf_token() }}"/>
Your problem come from a security control on the HTTP protocol called 'CORS' who prevent you from making a ajax call to another domain than the one your currently on.
To fix CORS issue you must implement a specific HEADER on the server. Since Google are not owned by you it a impossibility.
So to fix this issue you can use Google Api Service and make the API do the ajax call for you. Thats mean in Select2 you will need to use not ajax{url} but ajax{transport}.
Im not sure of that part but i suppose that the Google API will create himself a frame to is service site and from that same frame do all ajax request so CORS will not be a problem.
this is a working example:
https://jsfiddle.net/sebastienhawkins/b1ws2h07/
$(document).ready(function(){
$('.placecomplete').placecomplete({
placeServiceResult:function(data,status){
console.log(data);
$('#show_something').html(data.adr_address);
},
language:'fr'
});
});
//jquery.placecomplete.js file content
//! jquery.placecomplete.js
//! version : 0.0.1
//! authors : Sébastien Hawkins
//! license : Apache
(function($){
if(typeof $.fn.select2 == 'undefined'){
console.log("ERROR: Placecomplete need Select2 plugin.")
}
//Google services
var ac = null; //Autocomplete
var ps = null; //Place
//Google config
// https://developers.google.com/maps/documentation/javascript/reference#AutocompletionRequest
var googleAutocompleteOptions = {
types: ["geocode"]
};
//Google init
window.initGoogleMapsAPI = function(){
ac = new google.maps.places.AutocompleteService();
ps = new google.maps.places.PlacesService($('<div/>')[0]); //Google need a mandatory element to pass html result , we do not need this.
}
//Google Loading
if (window.google && google.maps && google.maps.places) {
window.initGoogleMapsAPI();
} else {
$.ajax({
url: "https://maps.googleapis.com/maps/api/js?libraries=places&sensor=false&callback=initGoogleMapsAPI",
dataType: "script",
cache: true
});
}
//Google placeservice result map
var placeServiceResult = function(data,status){
var CIVIC = 0, STREET = 1, CITY = 2, SECTEUR = 3, STATE = 4, COUNTRY = 5, ZIPCODE = 6;
//todo If the result does not have 7 element data map is not the same
//maybe we will need that html element google put mandatory
var adrc = data.address_components;
if(adrc.length != 7) return;
$('.address input.address').val(adrc[CIVIC].long_name +' '+ adrc[STREET].long_name);
$('.address input.city').val(adrc[CITY].long_name);
$('.address input.state').val(adrc[STATE].long_name);
$('.address input.country').val(adrc[COUNTRY].long_name);
$('.address input.zipcode').val(adrc[ZIPCODE].long_name);
}
//Select2 default options
var select2DefaultOptions = {
closeOnSelect: true,
debug: false,
dropdownAutoWidth: false,
//escapeMarkup: Utils.escapeMarkup,
language: 'en',
minimumInputLength: 2,
maximumInputLength: 0,
maximumSelectionLength: 0,
minimumResultsForSearch: 0,
selectOnClose: false,
theme: 'default',
width: 'resolve',
placeholder: {
id: '-1', // the value of the option
text: 'Search for address'
},
ajax:{
delay:100
}
};
//jQuery Plugin
var pluginDefault = {
placeServiceResult:placeServiceResult
}
$.fn.placecomplete = function (options) {
this.each(function () {
//Variable by instance
var $s2 = $(this);
//Init select2 for $this
$s2.select2($.extend(true,{
ajax: {
transport: function (params, success, failure) {
// is caching enabled?
//TODO(sébastien) ajouter le cache pour google autocomplete
if ($s2.data('ajax--cache')) {
}
else {
ac.getPlacePredictions($.extend(googleAutocompleteOptions,params.data),success);
}
},
data: function (params) {
return {input: params.term };
},
processResults: function (data, status) {
var response = {results:[]}
$.each(data,function(index,item){
item.text = item.description;
response.results.push(item)
});
return response;
}
}
}, select2DefaultOptions, options || {} ));
options = $.extend(true,pluginDefault,options);
$s2.on('select2:select', function (evt) {
ps.getDetails({ placeId: evt.params.data.place_id}, options.placeServiceResult);
});
});
return this;
};
})(jQuery);

load dynamic dropdownlist with json function but not working on ie 11

i have a function that works well in firefox and chrome But no in ie11, the problem is that the dropdown lists are showing empty and not data are coming to the select boxes.. :( please some help guys cause i m trying for ages to solve this with no lack..
my function is the following
function loadDynamicDdl(ajaxUrl , ddlId) {
$.ajax({
dataType:'json',
type: 'GET',
url: ajaxUrl,
cache:false,
async:false,
success:function (response) {
var ddl = $('#' + ddlId);
ddl.empty();
var opts = response.Options;
$.each(opts, function(i, item) {
ddl.append($("<option />").val(item.Value).text(item.DisplayText));
});
},
error:function (jqXHR, exception) {
//alert("There was an error loading dropdownlist.");
}
});
}
why omg is not working in internet explorer 11 ??? why,,, please guys i m about to break my head on the keyboard.. thank you in advance..
function loadDynamicDdl(ajaxUrl , ddlId) {
$.ajax({
dataType:'json',
type: 'GET',
url: ajaxUrl,
cache:true,
// contentType: "application/x-www-form-urlencoded;charset=UTF-8",
async:false,
success:function (response) {
if (response.Result == 'ERROR') {
$('#system-message-container').html('<h2 style="color:red;">' + response.Message + '</h2>');
$('#maincontent-container').hide();
}
var ddl = $('#' + ddlId);
ddl.empty();
var opts = response.Options;
//Not working when we have duplicates in json
// $.each(opts, function(i, item) {
// ddl.append($("<option />").val(item.Value).text(item.DisplayText));
// });
//Start checking for duplicates numbers in the Value field and DisplayTexts in json and push the uniques
var finalResult = [];
var Values =[];
var DisplayTexts = [];
$.each(opts, function (i, value) {
if ($.inArray(value.DisplayText, DisplayTexts) == -1 && ($.inArray(value.Value, Values) == -1)) { // it returns -1 when it doesn't find a match
Values.push(value.Value);
DisplayTexts.push(value.DisplayText);
finalResult.push(value);
ddl.append($("<option />").val(value.Value).text(value.DisplayText));
}
});
},
error:function (jqXHR, exception) {
//alert("There was an error loading dropdownlist.");
}
});
}

Return json object from dojo.xhrget

I am trying to get the json object from a dojo xhrGet call.
What I want is jsonobject = stuff;
I can see the json object in the console, but cannot access it!
var xhrargs = {
url: "/rest/url",
handleAs: "json",
preventCache : false,
load: function(json_results){
console.log(json_results);
store = json_results;
return dojo.toJson.json_results;
},
error: function(response, ioArgs) {
console.error(response);
console.error(response.stack);
}
};
var deferred = dojo.xhrGet(xhrargs);
console.log("Json is "+JSON.stringify(deferred));
The console.log part that shows the json_results is fine, exactly what I want.
The dojo.xhrXXX methods are asynchronous. This means that the lines following
var deferred = dojo.xhrGet(xhrargs);
Will continue to execute while the call to an external endpoint is processing. This means you need to use the promise API to tell a certain block of code to execute once the XHR request is complete:
var deferred = dojo.xhrGet(xhrargs);
deferred.then(function(result){
//this function executes when the deferred is resolved (complete)
console.log('result of xhr is ',result);
});
Due to the asynchronous nature of the request, for most intents and purposes that value doesn't exist outside the scope of the callback function. One way to structure your code around this is in multiple blocks. for example:
var xhrLoaded = function(results){
console.log('results = ',results);
store = results;
}
var performXhr = function(){
var xhrargs = {
url: "/rest/url",
handleAs: "json",
preventCache : false,
error: function(response, ioArgs) {
console.error(response);
console.error(response.stack);
}
};
var deferred = dojo.xhrGet(xhrargs);
deferred.then(xhrLoaded);
}
performXhr();
You can still access variables outside of the scope of the function (for example if store were defined globally).
try this
var xhrArgs = {
url:"MethodName.action?Id="+id,
handleAs: "json",
load: function(Data){
var values = Data;
var count = Object.keys(values).length // gives u all keys count in a json object. In mine it is 0,1,2,3
for (var i =0; i<count; i++){
var temp = values[i]; // values['name']
// do somthing ..
}
}
},
error: function(error){
alert(error);
}
}
dojo.xhrPost(xhrArgs);

how to get value JSON in google API

I have google API, it return a JSON file
http://maps.googleapis.com/maps/api/geocode/json?latlng=10.75,106.667&sensor=false
I want to get "long_name" : "Hồ Chí Minh", "long_name" : "Việt Nam" and "short_name" : "VN"
I don't know JSON, I do like this
var API = 'http://maps.googleapis.com/maps/api/geocode/json?latlng=10.75,106.667&sensor=false';
var obj = eval("(" + API + ")");
var obj2 = eval("(" + obj + ")");
document.getElementById("City").innerHTML = obj.results[0].obj2.address_components[0].long_name;
But it not working
I think you should read a little more about javascript. You must use a http get request to obtain the json, there is 2 ways to make this, using synchronous request or ajax request.
Try this :
//the json url
var API = 'http://maps.googleapis.com/maps/api/geocode/json?atlng=10.75,106.667&sensor=false';
//this function add the long_name
function addLongName(data){
var long_name = data.results[0].address_components[5].long_name;
document.getElementById("City").appendChild(document.createTextNode(long_name));
}
Using synchronous request
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", API, false);
try {
xmlHttp.send(null);
responseText = xmlHttp.responseText;
var data = JSON.parse(responseText);
addLongName(data);
} catch (ex) {
console.error(ex);
}
Using ajax request
var ajax = $.ajax({
type : "GET",
url : API,
dataType: 'jsonp',
success: function(data) {
addLongName(data);
}
});