I am learning Backbone and it would be great if someone can help me with this issue. After I do a fetch on my collection, in success callback I get the parsed data using collection.toJSON(), this actually returns an object and I am unable to get anything out of this object. This object actually has data that I need.
My question is how do I access rows property in my object. Here is my code for your reference
var testCollection = Backbone.Collection.extend({
model:myModel,
url: '/myApiEndPoint',
data: '',
initialize: function(models, options) {
this.data = models.data;
},
fetch: function(options) {
var ajaxConfig = {
url: this.url,
data: this.data,
type: 'POST',
dataType: 'text',
contentType: 'text/xml',
parse: true
};
options = _.extend({}, ajaxConfig, options);
return Backbone.Collection.prototype.fetch.call(this, options);
},
parse: function(xmlResponse) {
// I have some parsing logic to extract uid and rows from my xmlResponse
return {
uid: uid,
rows: rows
};
},
});
var collObj = new testCollection({data: xmlQuery1});
collObj.fetch({
success: function(collection){
// This code block will be triggered only after receiving the data.
console.log(collection.toJSON());
}
});
As the name toJSON suggests, it returns you the array of JSON objects where each object is a Model's JSON object. You can fetch the required properties in this way:
collObj.fetch({
success: function(collection){
// This code block will be triggered only after receiving the data.
console.log(collection.toJSON());
var uid = 'uid-of-an-object-to-access';
var rows = collection.get(uid).get('rows');
console.log(rows);
}
});
Related
I am using the Rasa X HTTP API to parse a yaml file and convert to a JSON object. I want to take this JSON object and then send it to my datatable to populate the rows. The problem is when I populate the datatable when calling the function in my datatable javascript, the JSON returns like this:
The API according to the docs here turns the payload into JSON format: https://rasa.com/docs/rasa-x/pages/http-api#operation/getDomain
Here is my code for the HTTP API:
export function getDomain(token) { //used to get auth token which is recreated each instance
var data = ""
//console.log(token);
var header_data = { Authorization: "Bearer " + token }
//console.log(header_data);
var sendData = {} //data to send. Check Rasa x API doc
$.ajax({
url: 'http://localhost:5002/api/domain',
type: 'GET',
async: false,
headers: header_data,
success: function (resp) {
//put name of json value you want to read after 'resp.'
//console.log(data);
var jsonDomain = yaml.parse(resp);
data = jsonDomain.entities;
console.log(typeof (data));
return data;
},
error: function (error) {
console.log('Error ${error}');
}
});
return data;
}
This function above parses the yaml file to get the data
export function getAuth() { //used to get auth token which is recreated each instance
var data = "";
var sendData = { "username": "me", "password":"huiwehfuiwfa" } //password changes each instance, there is a way to create a constant one too
$.ajax({
url: 'http://localhost:5002/api/auth',
//projects/default/intents',
type: 'POST',
async: false, //depracted but needs to be included to have it work
headers: {
"Access-Control-Allow-Origin": "*"
},
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(sendData),
success: function (resp) {
data = resp.access_token; //put name of json value you want to read after 'resp.'
return data;
},
error: function (error) {
console.log('Error ${error}');
}
});
return data;
}
This function gives authorization to use the API, gets the datatype as JSON, and stringifys it.
The console log for this shows as an object:
(3) ["plant", "water", "temperature"]
0: "plant"
1: "water"
2: "time"
length: 3
I then call this function to be able to use the data from the API in my datatables javascript:
import { getAuth, getDomain } from "./yaml.js";
export function populateTable() {
var token = getAuth();
var table_data = getDomain(token); // this gets the JSON data
var ieColumns = [{
title: "Name",
type: "text"
}];
var E = $('#Forestry').DataTable({
"sPaginationType": "full_numbers",
data: table_data,
columns: ieColumns,
dom: 'frtBip', // Needs button container
select: 'single',
responsive: true,
altEditor: true, // Enable altEditor
buttons: [
{
text: 'Add',
name: 'add' // do not change name
},
{
extend: 'selected', // Bind to Selected row
text: 'Edit',
name: 'edit' // do not change name
},
{
extend: 'selected', // Bind to Selected row
text: 'Delete',
name: 'delete' // do not change name
}
], style: "width:100%"
});
When I try to parse the JSON data using the parse function, I get an error from datatables complaining it is not in valid format.
I have also wrapped the function call getting the data from the API in brackets like this
var table_data = [getDomain(token)]; // this gets the JSON data
This returns one row with the first element in the JSON object which is plant but not the others.
The object type this returns is an array(3).
I want it to return each element in a separate row.
I'm trying to post a single object data to an MVC Controler using JQuery, Below are my codes.
//declare of type Object of GroupData
var GroupData = {};
//pass each data into the object
GroupData.groupName = $('#groupName').val();
GroupData.narration = $('#narration').val();
GroupData.investmentCode = $('#investmentCode').val();
GroupData.isNew = isNewItem;
//send to server
$.ajax({
url: "/Admin/SaveContributionInvestGroup",
type: "POST",
contentType: "application/json;charset=utf-8",
dataType: "json",
data: JSON.stringify({ GroupData: JSON.stringify(GroupData) }),
success: function (res) {
alertSuccess("Success", res.Message);
//hide modal
$('#product-options').modal('hide');
hide_waiting();
},
error: function (res) {
alertError("Error", res.Message);
}
});
Below is my controller.
[HttpPost]
public JsonResult SaveContributionInvestGroup(ContributionInvestmentGroup GroupData)
{
ClsResponse response = new ClsResponse();
ClsContributionInvestmentGroup clsClsContributionInvestmentGroup = new ClsContributionInvestmentGroup();
var userID = (int)Session["userID"];
var sessionID = (Session["sessionID"]).ToString();
if (contributionGroupData != null)
{
//get the data from the cient that was passed
ContributionInvestmentGroup objData = new ContributionInvestmentGroup()
{
contributionInvestmentGroupID = 0,
groupName = GroupData.groupName,
narration = GroupData.narration,
investmentCode = GroupData.investmentCode,
isNew = GroupData.isNew
};
response = clsClsContributionInvestmentGroup.initiateNewContributionInvestmentGroup(sessionID, objData);
}
else
{
response.IsException = true;
response.IsSucess = false;
response.Message = "A system exception occurred kindly contact your Administrator.";
}
return Json(new
{
response.IsSucess,
response.Message
});
}
The issue is, the data is not been posted to the controller, the controller receives a null object.
Kindly assist, would really appreciate your effort, thanks.
Try Like this:
//send to server
$.ajax({
type: "POST",
url: "/Admin/SaveContributionInvestGroup",
dataType: "json",
data: GroupData,
success: function (res) {
alertSuccess("Success", res.Message);
//hide modal
$('#product-options').modal('hide');
hide_waiting();
},
error: function (res) {
alertError("Error", res.Message);
}
});
in your controller your dont have custom binding to bind JSON to your model thats why you get null in you parameter.
instead just post it as query, try simply changes your ajax option like so:
{
...
contentType: "application/x-www-form-urlencoded", //default:
...,
data: $.param(GroupData),
...
}
and perhaps property names are case sensitive so you will need to change your javascript model's name
is there a way to pass an array of object and then assign it to model?
i searched that making the same variable name in your model and object will do the work but it doesn't work for me.
the model always get null values.
var answers = [];
var answerOthers = [];
var comment = $("#message").val();
$("input:radio:checked").each(function () {
var questno = $(this).attr("data-question");
var ansid = $(this).val();
answers.push({ QUESTIONID: questno, ANSWERID: ansid});
if ($(this).val() == 3)
{
var txtOther = $("#otherTxt-" + $(this).attr("data-question")).val();
answerOthers.push({
QUESTIONID: questno,
ANSWER: txtOther
});
}
});
$.ajax({
url: 'insertQuestions',
data: { answers: answers, answer_others: answerOthers, userid: userid , comment: comment },
method: 'GET',
success: function ()
{
alert("saved");
},
error: function (e)
{
console.log(e);
}
});
c# controller
public void insertQuestions(List<ratingsModel.ANSWERS> answers,
List<ratingsModel.ANSWERS_OTHERS> answer_others, int userid , string comment)
{
insertAnswers(answers,userid);
insertAnswer_others(answer_others, userid);
MySqlConnection myconn2 = new MySqlConnection(cmn.connstring);
myconn2.Open();
string query3 = "INSERT INTO comments (userid,comment) VALUES" +
" (#userid,#comment)";
MySqlCommand cmd2 = new MySqlCommand(query3, myconn2);
cmd2.Parameters.AddWithValue("#userid", userid);
cmd2.Parameters.AddWithValue("#comment", comment);
cmd2.ExecuteNonQuery();
myconn2.Close();
}
You cannot do that with a GET (the data you pass to the method would need to be a query string and to represent your collections you need individual name/value pairs with collection indexers, for example
data { [0].QUESTIONID: xx, [0].ANSWERID: yy [1].QUESTIONID: zz, .... etc }
But it should not be a GET in any case. Your method is changing data so it should be a POST (and in addition, if your collections were large, your would exceed the query string limit and throw an exception)
Change the ajax code to
$.ajax({
url: #Url.Action('insertQuestions'), // dont hard code your url's
data: JSON.stringify({ answers: answers, answer_others: answerOthers, userid: userid, comment: comment }) // modify,
contentType: 'application/json', // add
method: 'POST', // change
success: function() {
....
As a side note, if you had generated your form correctly using the strongly typed HtmlHelper methods, then you code could simply have been
$.ajax({
url: #Url.Action('insertQuestions'),
data: $('form').serialize(),
method: 'POST',
success: function() {
....
and none of the code for generating the arrays would be required.
I'm using KnockoutJS...
I have an observableArray of movies in my viewModel. The array is updated when a user searches for a movie by title, so a typical json response that would be pushed into the array would look like this...
{data : [{
Id: 12345,
Title: 'Movie1',
Year: 2010,
Character: [{
Name: 'Character1',
Person: { Id: 1, Name: 'Person1' }
},{
Name: 'Character2',
Person: { Id: 2, Name: 'Person2' }
}],
UserMovies: [{
Id: 8
IsWatched: false,
Rating: 3.5,
UserId: 'e1e9c075-1ded-4e7d-8d30-d5d1fbd47103'
}]
}]}
The UserMovies property of each movie represents information specific to that user, like their personal rating or if they've watched the movie yet, etc.
I give the user the ability to "Add" the movie to their collection in the database. When they add the movie to their collection a json response is sent back that has the updated UserMovies property for that movie.
I'm trying to update just that property and then have it persist to the knockout template. Here's my current viewModel...
function viewModel() {
// private properties
var self = this;
// public properties
self.movies = ko.observableArray([]);
self.searchValue = ko.observable();
// public operations
self.search = function () {
self.isLoading(true);
$.getJSON(arguments[0].action, { name: this.searchValue() }, function (data) {
self.movies(data);
});
};
self.add = function (movie) {
$.ajax({
type: 'POST',
url: arguments[1].currentTarget.attributes[1].value,
data: JSON.stringify({ movie: movie }),
contentType: 'application/json',
dataType: 'json',
success: function (data) {
// how to just update UserMovies property and persist to template for the given movie?
}
});
};
}
ko.applyBindings(new viewModel());
I'm not sure how to update the property but as far as persisting the data to the knockout template I think it's because the UserMovies property of each movie isn't itself an observable so if it's updated nothing will automatically change in the template.
I've been reading about the mapping plugin which would make every property an observable. This may fix my persistance problem but I'm still unsure how to update just the UserMovies property whether it's in an observableArray or via the mapping plugin.
Update
I've created a fiddle using the mapping plugin. If I return the whole movie instead of just the UserMovies property it will be much easier to update an item in the array. I'm having some issues getting it to work though and I'm struggling to figure out how to create a mapping for 'key' against the UserMovies property. http://jsfiddle.net/cmBd9/3/
As you yourself correctly note, the fact that the UserMovies property is not an observable means that even if you update it, nothing will happen in the UI. Nonetheless, here is how you could update the (non-observable) UserMovies:
self.add = function (movie) {
$.ajax({
type: 'POST',
url: arguments[1].currentTarget.attributes[1].value,
data: JSON.stringify({ movie: movie }),
contentType: 'application/json',
dataType: 'json',
success: function (data) {
ko.utils.arrayForEach(self.movies(), function(m) {
if (m.Id == movie.Id) {
m.UserMovies = data;
}
});
}
});
};
Definitely check out the mapping plugin. My only concern is that the documentation shows how to initially map an object from JSON, and how later to update the entire object from JSON.
However, it doesn't seem to mention anything about mapping an object from JSON and later coming along and updating only part of that object from JSON, so I'm not sure if that will work or not.
If you have trouble, you could try having the service call for the add method return the entire movie object so that you are more closely following the model espoused by the mapping plugin.
I was able to get it to work with the mapping plugin using mapping options. I set the key for UserMovies to be the Id of each UserMovie so when fromJS() is called it will look to the Id of each UserMovie to tell whether to update or add a new UserMovie
Here's my updated code...
function viewModel() {
// private properties
var self = this;
var mapping = {
'UserMovies': {
key: function (data) {
return ko.utils.unwrapObservable(data.Id);
}
}
};
// public properties
self.movies = ko.mapping.fromJS([]);
self.searchValue = ko.observable();
// public operations
self.search = function () {
self.isLoading(true);
$.getJSON(arguments[0].action, { name: this.searchValue() }, function (data) {
ko.mapping.fromJS(data, {}, self.movies);
});
};
self.add = function (movie) {
$.ajax({
type: 'POST',
url: arguments[1].currentTarget.attributes[1].value,
data: ko.toJSON({ movie: movie }),
contentType: 'application/json',
dataType: 'json',
success: function (data) {
if(data.success) {
ko.mapping.fromJS(data.movie, mapping, movie);
}
}
});
};
}
I am sending json list from my controller:
public ActionResult LoadTree()
{
List<ListItem> list = new List<ListItem>() {
new ListItem() { Text = "Keyvan Nayyeri" },
new ListItem() { Text = "Simone Chiaretta" },
new ListItem() { Text = "Scott Guthrie" },
new ListItem() { Text = "Scott Hanselman" },
new ListItem() { Text = "Phil Haack" },
new ListItem() { Text = "Rob Conery" }
};
return new JsonResult { Data = list };
}
Trying to get the list in my view using:
var text =
$.ajax({
url: '/CourseCases/LoadTree',
dataType: 'json',
data: { },
cache: false,
type: 'GET',
success: function (data) {
}
});
alert(text);
I just get [object object]. How I can get the actual value of the object? Thanks in advance.
First you have to set the JsonRequestBehavior = JsonRequestBehavior.AllowGet in the JsonResult.
public ActionResult LoadTree()
{
List<ListItem> list = new List<ListItem>() {
new ListItem() { Text = "Keyvan Nayyeri" },
new ListItem() { Text = "Simone Chiaretta" },
new ListItem() { Text = "Scott Guthrie" },
new ListItem() { Text = "Scott Hanselman" },
new ListItem() { Text = "Phil Haack" },
new ListItem() { Text = "Rob Conery" }
};
return new JsonResult { Data = list, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
<script type="text/javascript">
$.ajax({
url: '/Home/LoadTree',
dataType: 'json',
data: {},
cache: false,
type: 'GET',
success: function (data) {
alert(data.length); // 6
// do whatever with the data
}
});
</script>
in success function you have to parse json to get actual data e.g.
var jsObject = JSON.parse(data);
and then access each item like jsObject.List[0].Text etc
Simple problem here. In your controller, you're actually assigning the list to a variable named Data inside the response data collection. Just because your success function takes a data parameter doesn't mean that the Data value you set in your controller automagically will become the data variable.
As your Data list is inside the data object: you need to do:
data.Data
inside your success function. Try this:
success: function(data) {
alert(data.Data.length);
}
function $.ajax() does not return value from server, so var text = $.ajax() will not work. You need to look at success handler instead
success: function (data) {
// data is the result of your ajax request
}
I strongly recommend you to read more at jQuery.Ajax
success(data, textStatus, jqXHR) A function to be
called if the request succeeds. The function gets passed three
arguments: The data returned from the server, formatted according to
the dataType parameter; a string describing the status; and the jqXHR
(in jQuery 1.4.x, XMLHttpRequest) object. As of jQuery 1.5, the
success setting can accept an array of functions. Each function will
be called in turn. This is an Ajax Event.