Can't assign json data from controller to data in HighStock - json

I'm trying to load json data from controller Jsonresult in MVC 4 but it doesn't seems to work in HighStock. The data was serialized and the alert it popping up and displaying the data. I don't know why the chart is not rendering. But it is working when i create a variable like var data = [1,2] in the javascript function.
<script type="text/javascript">
$(function () {
$.getJSON('GetData', function (data) {
alert(data);
var data1 = [1, 2];
alert(data1);
// Create the chart
$('#container').highcharts('StockChart', {
rangeSelector: {
selected: 1
},
title: {
text: 'AAPL Stock Price'
},
series: [{
name: 'AAPL',
data: data,
tooltip: {
valueDecimals: 2
}
}]
});
});
});
[HttpGet]
public JsonResult GetData()
{
string sample = "[1,2]";
var jss = new JavaScriptSerializer();
var output = jss.Serialize( sample );
return Json( output, JsonRequestBehavior.AllowGet );
}

Related

Backbone - parsing JSON ID

I'm trying to parse JSON data using Backbone from a remote API. Here's what I've got so far:
// --------------------------------------------------
// MODELS
// --------------------------------------------------
var VideoModel = Backbone.Model.extend({
idAttribute: '_id',
parse: function(){
this.id = response._id;
}
});
var videoModel = new VideoModel({ parse:true });
// --------------------------------------------------
// COLLECTIONS
// --------------------------------------------------
var VideosCollection = Backbone.Collection.extend({
model: VideoModel,
url: 'redacted',
parse: function(response){
this.videos = response.data;
this.cid = response.cid;
return response.data;
},
render: function(){
this.collection.forEach(this.addone, this);
}
});
var videosCollection = new VideosCollection();
videosCollection.fetch({
success: function(videos){
console.log('success!');
},
error: function(){
console.log('failed.');
}
});
// --------------------------------------------------
// VIEWS
// --------------------------------------------------
var VideoView = Backbone.View.extend({
template: _.template('<%= videoModel.id %>'),
render: function(){
this$el.html(this.template(this.model.attributes));
return this;
}
});
var videoView = new VideoView({});
var VideosCollectionView = Backbone.View.extend({});
var videosCollectionView = new VideosCollectionView({
collection: videosCollection,
render: function(){
this.collection.forEach(this.addOne, this);
},
addOne: function(videoModel){
this.$el.append(videoView.el);
}
});
What I'm having trouble with is that console.log(videoModel.id) is still undefined.
The data is a playlist of videos, which is valid JSON:
{
"total":24,
"per_page":24,
"current_page":1,
"last_page":1,
"from":1,
"to":24,
"data":[
{
"_id":"55d1bb50140ba04c1d8b4583",
Be glad for some prompts in the right direction - especially since I had it working this morning and then ... reverted to a previous version without saving.
Thanks
From documentstion of parse method:
The function is passed the raw response object, and should return the
attributes hash to be set on the model. The default implementation is
a no-op, simply passing through the JSON response.
So by default it works like this:
parse: function(data) {
return data;
}
Your code now returns nothing and model takes no data.
As I see you want to set id attribute but you already have setted idAttribute property with _id and there is _id in your data so it should work fine without parse at all. Try to remove it.
The answer is that I was trying to parse via a Collection instead of a Model. So I would never have got the id I was looking for. For some reason.
I needed to move the URL into the Model and parse from there:
var VideoModel = Backbone.Model.extend({
idAttribute: '_id',
url: 'redacted',
parse: function(response){
var id = response._id;
var cid = response.cid;
return response.data;
},
}),
Now when I do videoModel.get(1) in the console, it returns the value of the first item in my array.

How to convert Backbone fetched object to proper Handlebars JSON Object?

Currently I have an issue with getting back a proper JSON object I'm fetching with Backbone fetch() and putting it into a Handlebars template.
See below my code, I have made a ugly workaround for now to test my Backend API
When converting to JSON with *.toJSON(), it just adds an extra object in-between and I don't need this extra object
Object [0]
--> books
----> Object [0]
------> Array of book
--------> book
--------> cities
JSON
{
"books": [
{
"book": 00001,
"cities": [
"TEST"
]
},
{
"book": 00002,
"cities": [
"TEST"
]
},
{
"book": 00003,
"cities": [
"TEST"
]
}
],
"more": true
}
JavaScript
var Book = Backbone.Model.extend({
default: {
book: 0,
cities: ["TEST1", "TEST2", "TEST3"]
},
url: function () {
return ".list.json";
}
});
var Books = Backbone.Collection.extend({
model: Book,
url: ".list.json"
});
var BooksView = Backbone.View.extend({
initialize: function(){
_.bindAll(this, 'render');
this.collection = new Books();
this.collection.fetch();
this.source = $('.e-books-template').html();
// Use an extern template
this.template = Handlebars.compile(this.source);
var self = this;
this.collection.fetch({
success: function () {
self.render();
},
error: function () {
console.log("ERROR IN BooksView");
}
});
},
render: function() {
var collect = JSON.stringify(this.collection);
collect = collect.slice(1, -1);
var html = this.template($.parseJSON(collect));
this.$el.html(html);
}
});
var booksView = new BooksView({ });
$(document).ready(function(){
booksView.$el = $('.e-books-content');
});
A Backbone collection expects an array of models but your JSON provides an object with the array under a books key. Parse the server response to format the data :
var Books = Backbone.Collection.extend({
model: Book,
url: ".list.json",
parse: function(data) {
return data.books;
}
});
Pass your data to your template via http://backbonejs.org/#Collection-toJSON ,
// directly as an array in your template
var html = this.template(this.collection.toJSON());
// under a books key
var html = this.template({
books: this.collection.toJSON()
});
And a demo http://jsfiddle.net/nikoshr/8jdb13jg/

Plotting Multiple JSON data in flot chart using angularjs

I am using angularjs and JSON to plot flot chart, i am using multiple encoded JSON to draw the line of the Flot line chart, doing so the bar comes out empty.
Not quite sure what is wrong.
HTML
<flot id="placeholder" dataset="dataset" options="options" height="250px"></flot>
JS
.factory("services", ['$http', function($http) {
var serviceBase = 'http://maricoih.e21designs.com/services/'
var obj = {};
obj.getope = function(){
return $http.get(serviceBase + 'productionhourlys');
}
obj.getcopra = function(){
return $http.get(serviceBase + 'productionhourlyscopra');
}
return obj;
}])
.controller('LineChartCtrl', function ($scope,$http,services) {
$scope.dataset = [{
data: obj.getope(),
label: 'OPE',
points: {
show: true,
radius: 6
}
}, {
data: obj.getcopra(),
label: 'OEE',
points: {
show: true,
radius: 6
}
}];
})

Backbone toJSON not rending

I am a complete n00b to Backbone.js, and have only been working with it for a few days. I am attempting to fetch JSON data to populate the model, and in this scenario I have two models that I need to generate. Here is the sample JSON I have been working with:
JSON
{
"status": "200",
"total": "2",
"items":
[{
"id": "1",
"name": "Here is another name",
"label": "Label for test",
"description": "A description for more information.",
"dataAdded": "123456789",
"lastModified": "987654321"
},
{
"id": "2",
"name": "Name of item",
"label": "Test Label",
"description": "This is just a long description.",
"dataAdded": "147258369",
"lastModified": "963852741"
}]
}
Backbone JS
// MODEL
var Service = Backbone.Model.extend({
defaults: {
id: '',
name: '',
label: '',
description: '',
dateAdded: '',
dateModified: ''
}
});
var service = new Service();
// COLLECTION
var ServiceList = Backbone.Collection.extend({
model: Service,
url: "./api/service.php",
parse: function(response) {
return response.items;
}
});
//
var serviceList = new ServiceList();
var jqXHR = serviceList.fetch({
success: function() {
console.log("Working!");
console.log(serviceList.length);
},
error: function() {
console.log("Failed to fetch!");
}
});
// VIEW for each Model
var ServiceView = Backbone.View.extend({
el: $('.widget-content'),
tagName: 'div',
template: _.template($('#service-template').html()),
initialize: function() {
this.collection.bind("reset", this.render, this);
},
render: function() {
console.log(this.collection);
this.$el.html('');
var self = this;
this.collection.each(function(model) {
self.$el.append(self.template(model.toJSON()));
});
return this;
}
});
//
var serviceView = new ServiceView({
collection: serviceList
});
console.log(serviceView.render().el);
html
<div class="widget-content">
<!-- Template -->
<script type="text/template" id="service-template">
<div><%= name %></div>
</script>
</div>
When I console log the serviceList.length I get the value 2, so I believe the JSON object is fetched successfully. I also get the "Working!" response for success too. However, in the view I am showing an empty object, which gives me an empty model.
I am still trying to understand the best way to do this too. Maybe I should be using collections for the "items" and then mapping over the collection for each model data? What am I doing wrong? Any advice or help is greatly appreciated.
I can see two problems. First, you want to remove serviceList.reset(list). Your collection should be populated automatically by the call to fetch. (In any case the return value of fetch is not the data result from the server, it is the "jqXHR" object).
var serviceList = new ServiceList();
var jqXHR = serviceList.fetch({
success: function(collection, response) {
console.log("Working!");
// this is the asynchronous callback, where "serviceList" should have data
console.log(serviceList.length);
console.log("Collection populated: " + JSON.stringify(collection.toJSON()));
},
error: function() {
console.log("Failed to fetch!");
}
});
// here, "serviceList" will not be populated yet
Second, you probably want to pass the serviceList instance into the view as its "collection". As it is, you're passing an empty model instance into the view.
var serviceView = new ServiceView({
collection: serviceList
});
And for the view, render using the collection:
var ServiceView = Backbone.View.extend({
// ...
initialize: function() {
// render when the collection is reset
this.collection.bind("reset", this.render, this);
},
render: function() {
console.log("Collection rendering: " + JSON.stringify(this.collection.toJSON()));
// start by clearing the view
this.$el.html('');
// loop through the collection and render each model
var self = this;
this.collection.each(function(model) {
self.$el.append(self.template(model.toJSON()));
});
return this;
}
});
Here's a Fiddle demo.
The call serviceList.fetch is made asynchronously, so when you try console.log(serviceList.length); the server has not yet send it's response that's why you get the the value 1, try this :
var list = serviceList.fetch({
success: function() {
console.log(serviceList.length);
console.log("Working!");
},
error: function() {
console.log("Failed to fetch!");
}
});

Bootstrap typeahead ajax result format - Example

I am using Bootstrap typeahead with an ajax function, and want to know what is the correct Json result format, to return an Id and a descripcion.
I need the Id to bind the typeahead selected element with a mvc3 model.
This is the code:
[Html]
<input id="myTypeahead" class='ajax-typeahead' type="text" data-link="myUrl" data-provide="typeahead" />
[Javascript]
$('#myTypeahead').typeahead({
source: function (query, process) {
return $.ajax({
url: $('#myTypeahead').data('link'),
type: 'post',
data: { query: query },
dataType: 'json',
success: function (jsonResult) {
return typeof jsonResult == 'undefined' ? false : process(jsonResult);
}
});
}
});
This works properly when I return a simple list of strings, for example:
{item1, item2, item3}
But I want to return a list with Id, for example:
{
{Id: 1, value: item1},
{Id: 2, value: item2},
{Id: 3, value: item3}
}
How to process this result in the ajax "success: function()"?
That is very easy with jquery Autocomplete, because I can return a Json Object list.
[jquery Autocomplete process data example]
...
success: function (data) {
response($.map(data, function (item) {
return { label: item.Id, value: item.Value, id: item.Id, data: item };
})
...
But that doesn't work with boostrap Typeahead.
Can anyone help me?
Thanks.
I try for two days and finally I could it working.
Bootstrap Typeahead doesn't support an array of objects as a result by default, only an array of string. Because "matcher", "sorter", "updater" and "highlighter" functions expect strings as parameter.
Instead, "Bootstrap" supports customizable "matcher", "sorter", "updater" and "highlighter" functions. So we can rewrite those functions in Typeahead options.
II used Json format, and bound the Id to a hidden html input.
The code:
$('#myTypeahead').typeahead({
source: function (query, process) {
return $.ajax({
url: $('#myTypeahead').data('link'),
type: 'post',
data: { query: query },
dataType: 'json',
success: function (result) {
var resultList = result.map(function (item) {
var aItem = { id: item.Id, name: item.Name };
return JSON.stringify(aItem);
});
return process(resultList);
}
});
},
matcher: function (obj) {
var item = JSON.parse(obj);
return ~item.name.toLowerCase().indexOf(this.query.toLowerCase())
},
sorter: function (items) {
var beginswith = [], caseSensitive = [], caseInsensitive = [], item;
while (aItem = items.shift()) {
var item = JSON.parse(aItem);
if (!item.name.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(JSON.stringify(item));
else if (~item.name.indexOf(this.query)) caseSensitive.push(JSON.stringify(item));
else caseInsensitive.push(JSON.stringify(item));
}
return beginswith.concat(caseSensitive, caseInsensitive)
},
highlighter: function (obj) {
var item = JSON.parse(obj);
var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
return item.name.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
return '<strong>' + match + '</strong>'
})
},
updater: function (obj) {
var item = JSON.parse(obj);
$('#IdControl').attr('value', item.id);
return item.name;
}
});
Note: I saw #EralpB`s comment "Is this still the best way to accomplish this task?"
Yes, #Gonzalo solution works, but it seems strange (like crutch,especially after using jQuery-Autocomplete) - it should work "from box".Better is to use this - Bootstrap-3-Typeahead. It supports an array of objects as result: format - [{id: .. ,name:...},...,{id: .. ,name:...}]. Example for OP`s issue:
....
source: function (query, process) {
return $.ajax({
......
success: function (result) {
var resultList = [];
$.map(result,function (Id,value) {
var aItem = { id: Id, name: value};
resultList.push(aItem);
});
return process(resultList);
}
});
},