Unable to access JSON element - javascript

I am using the following code in Win API Controller to return an object containing a Menu object and a list of CourseOption objects.
public object GetCourseOption(int id) //Here id is Menu id
{
IEnumerable<CourseOption> courseoptions = db.CourseOptions.Where(c => c.MenuId == id);
Menu menu = db.Menus.Single(c => c.Id == id);
if (courseoptions == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
var combine = new { Menu = menu, Options = courseoptions };
return combine;
}
I can access Menu properties by using the following code in JavaScript
$.getJSON("/api/CourseOptionAPI/" + id, function (data) {
alert("In " + data.Menu.Name);
});
but unable to access CourseOption properties by the following code
alert("In " + data.Options[0].Name);
The controller method is returning Options as part of 'combine' object (i have checked it by using breakpoint).
'Menu' and 'CourseOption' are objects and 'Name' is one of their properties (in both of them) of type string.

Name may be one of the properties, but it looks like if c.MenuId == id keeps failing, you're never going to respond with any useful data and data.Options[0] will be undefined.
Like #zerkms said, console.log your incoming data and check what is in the JSON received.

Related

How do I destructure this deep nested object?

I have this function below:
const displayUserPhotoAndName = (data) => {
if(!data) return;
// add your code here
clearNotice();
};
the data parameter is an API from https://randomuser.me/api/
The assignment has the instructions below:
Locate the displayUserPhotoAndName function and do the follwing within it:
After the first if(!data) return; statement that terminates the
function if the expected data parameter is not provided, create a
statement that de-structures the data parameter and obtains the
results property from it;
Create a second statement in the next line that de-structures the
results variable you just created, and obtain the first item from it
(it is an Array! See https://randomuser.me/api/). Your de-structured
array item should be declared as profile. This represents the profile
data for the user gotten from the API call that you want to display
in your app.
Step 3
Still within the displayUserPhotoAndName function :
Set the HEADING element in your app to display the title, last name,
and first name (in that order, separated by a single space) of the
user profile returned by the API.
Set the IMG in your app to display the large photo of the user
profile returned by the API.
what I have done:
const displayUserPhotoAndName = (data) => {
if(!data) return;
// add your code here
const {results} = data.results;
const [profile] = results;
const {title, First, Last} = results;
const [,,,,,,,,,picture] = results;
const largeImage = picture.large;
userImage.src = largeImage;
headerUserInfo.innerText = title + ' ' + First + ' ' + Last;
clearNotice();
displayExtraUserInfo(profile);
};
The error I get:
You have not de-structured the 'results' property from the 'data'
parameter passed to 'displayUserPhotoAndName' function
I'm in dire need of assistance. Thanks in anticipation
I'm not going to provide you the full answer but giving you the hints:
const { results } = data
const { profile } = results
console.log(profile)
Can be written as:
const { results: { profile } } = data
console.log(profile)
Here are my some posts from which you may go further:
destructure an objects properties
how is this type annotation working
why source target when destructuring

Is there another way to set initial values on a Kendo virtualized mutliselect widget?

I have a kendo multi-select widget that is bound to a lot of data, to handle this I have virtualized the widget and put the stress onto the server.
I'm trying to select some initial data via a javascript function that passes an array of Ids. It works well only if the data that's being selected is on the first paged result set of the widget, if any of the Ids are further in then they are not selected and I need to fix it.
Here is the code for my widget:
#(Html.Kendo().MultiSelect()
.Name("Cars")
.DataTextField("Name")
.DataValueField("Id")
.Placeholder("Select cars...")
.Filter(FilterType.Contains)
.DataSource(source => { source
.Custom()
.ServerFiltering(true)
.Events(e => e.Error("errorHandler"))
.ServerPaging(true)
.PageSize(80)
.Type("aspnetmvc-ajax")
.Transport(transport => {
transport.Read("GetData", "Positions");
})
.Schema(schema => { schema
.Data("Data")
.Total("Total")
.Errors("Errors");
});
}))
The data is received from the GetData Method of the Positions controller which is tied to my cars repository.
GetData
public JsonResult GetData([DataSourceRequest] DataSourceRequest request)
{
var car = unitOfWork.CarRepository.Get().OrderBy(n => n.Name);
var results = vessel.ToDataSourceResult(request);
return Json(results);
}
Here is my function that runs after user input (button). I've added a sample array to show you what's passed in.
InitialSelection
function initialSelection(filter) {
//filter is: "6544","4880","6545","6548"
var carSelection = $("#Cars").data("kendoMultiSelect");
var filterArray = filter.split(',').map(Number);
if (filterArray.length > 0) {
console.log(filterArray)
carSelection.value(filterArray);
} else {
carSelection.value();
}
}
Is there a better way to make an initial selection of data than what I'm doing with the above javascript? As I said, if the ids are not on the first page of results that are returned, they are not selected which is frustrating.
You could simply change the read declaration to something like this:
.Transport(transport => {
transport.Read(read => read.Action("GetData", "Positions").Data("intialvalues"));
})
Then add a function for the initialvalues data object like:
function inititalvalues(){
var filterArray = filter.split(',').map(Number);
if(filterArray === undefined || filterArray === null || filterArray.length <= 0)
{
filterArray = []
}
return {filterValues: filterArray};
}
then in your read method on your controller you add the following:
public JsonResult GetData([DataSourceRequest] DataSourceRequest request, List<int> filterValues)
{
if (filterValues.Count > 0 && request.Page == 1)
{
..get the first page minus how many filterValues you have to inject the selected Items at the top of the list...
}
else if (filterValues.Count > 0 && request.Page > 1)
{
..get the page you need and remove any selected items from the page as they will be at the top...
}
else
{
..just get everything as normal as nothing should be selected at this stage.
}
return your paged resultset back...
}
hopefully that gives you a starting point.

Reading Json data from Knockout.Js using javascript

I am using knockout where I get my JSON object using Ajax. My question is how do I use this data in my own javascript code:
I have my mapped item, which is what I get returned from the ajax.
Example:
MedarbejderId: ko.observable(element.MedarbejderId),
MedarbejderId is the Id I need to find the name in my following method.
function TranslateMed(i)
{
console.log("test " + i) // for testing purposes in console.
for (var key in obj)
{
if (obj[key].Value == i)
{
console.log("vi er inde");
return obj[key].Text;
}
}
return obj[0].Text
}
obj is my List of names. this works fine. My issue comes when i save the Data,
$(document).on("click", ".kout-update", null, function (ev) {
var current = ko.dataFor(this);
console.log(current);
current.MedarbejderNavn = TranslateMed(current.MedarbejderId);
current.Mode("display");
saveData(current);
});
here my current.MedarbejderId is c(){if(0<arguments.length)return c.Ua(c[F],arguments[0])&&(c.ia(),c[F]=arguments[0],c.ha()),this;a.l.sc(c);return c[F]}
I need to get the Value of it instead.
The solution i found was that i needed to treat
current.MedarbejderNavn = TranslateMed(current.MedarbejderId);
Diffrently, so when i changed it to:
current.MedarbejderNavn = TranslateMed(current.MedarbejderId());

Set id attribute after success of ajax call in Kineticjs

I'm using KineticJS in my MVC application.
In order to retrieve data from database, I'm making some ajax calls to web services in the API controller. There is an API that returns an id, which I want to assign to the current Kinetic.Group id attribute on success.
After drag and drop, a popup PopUpAddRoom(FloorId) appears and calls the AddRoom function.
my code:
function AddRoom(FloorId, RoomName, TypeID) {
$.ajax({
beforeSend: function (xhr) { // verify session },
url: "/api/someurl", //url for adding the room, that returns room's id
type: "Post",
dataType: 'json',
success: function (data) {
//data is the room id
var r = rightLayer.find("#" + data)[0];
console.log(r.getType()); // here I don't even get the type, I get "Object []"
var rec = r.find("Rect"); //rec is a rectangle inside the group
rec.setId(data);
rightLayer.draw();
}
});
}
The problem is that r = rightLayer.find("#" + data)[0]; is empty. It returns undefined.
When I call console.log(data); to see if data's content is empty, it returns the correct id !
I initialized the id like this: id: '' and want it to change as it gets the data from database. But this failed. Is there something wrong with this code?
EDIT :
After figuring out that id: '' is really dumb idea (with the help of markE), I tried initializing id to an empty variable ident which gets its value from a web service (this ws increments the id when a new instance is added successfully).
But the problem doesn't come from r = rightLayer.find("#" + data)[0];. It's the fact of assigning the id to a node (location of the instruction)
var ident;
var group = new Kinetic.Group({
...
id: ident
...
});
I added then this line: ident = data; after success of the ajax call, still the same error. It seems like this instruction isn't doing nothing. The value of ident isn't changing after that I call PopUpAddRoom function.
If you initialize the desired node's id to the empty string:
id:''
then this .find will never retrieve that desired node:
var r = rightLayer.find("#" + data);
Instead do something like this:
...
id:'replaceable1'
...
var r = rightLayer.find("#replaceable1")[0];
var rec = r.find("Rect")[0];
// change the id of both r and rec
r.setId(data);
rec.setId(data);
Note that .find always returns a collection (like a fancy array) so to get a reference to an element within that array you must do [n]. For example myLayer.find(something)[0].
According to KineticJS docs:
find(selector) --> return a Kinetic.Collection of nodes that match the selector
So if find returns a collection, in order for you to get the layer, I think something like:
var r = rightLayer.find("#" + data)[0];
should work, taking into account that id's in KineticJS shapes are unique.

Nested Queries returning UNDEFINED using javascript and parse.com database

I have two classes within my parse database one called "TrebUser" and the other called "UserImage" described as follows:
TrebUser
----------------------------------------------------
| objectID | firstname | lastname | image |
(string) (string) (string) (UserImage ObjectId)
UserImage
------------------------------------
| objectID | image | imagename |
(string) (file) (string)
For a given TrebUser I want to display a profile which includes their firstname, lastname, and shows the imagename (once I manage to get the image name displayed i will attempt to actually display the image). I am attempting to use one query to retrieve the TrebUser, and then a second nested query, or promise (as i have used below), to retrieve the imagename for that user, and then return that imagename back to where I will print it on the screen. For some reason it always comes back as undefined even though when I use a popup alert it is showing the name just fine. I think this has something to do with asynchronous execution. Any thoughts?
function getPhoto(i){
var TrebUser = Parse.Object.extend("TrebUser");
var queryTrebUser = new Parse.Query(TrebUser);
var UserImage = Parse.Object.extend("UserImage");
var queryUserImage = new Parse.Query(UserImage);
queryTrebUser.find().then(function(results) {
alert("Successfully retrieved " + results.length + "object");
var object = results[i];
var imageId = object.get('image').id;
queryUserImage.equalTo("objectId", imageId);
return queryUserImage.find();
}).then(function(imageResults) {
var object2 = imageResults[i];
//this alert shows the image 'name' perfectly, however when i return the object2.get('name') it shows
//up as undefined!
alert("Successfully retrieved " + imageResults.length + " object with name " + object2.get('name'));
return object2.get('name');
}, function(error) {
alert("Error: " + error.code + " " + error.message);
});
}
You should instead just use the .include(key) method, e.g.
var TrebUser = Parse.Object.extend("TrebUser");
var queryTrebUser = new Parse.Query(TrebUser);
queryTrebUser.include("image");
queryTrebUser.find().then(function(results) {
alert("Successfully retrieved " + results.length + "object");
var object = results[i];
var image = object.get('image');
var imageName = image.get('name');
});
I would highly question a few things you're doing based on the code you have provided. Perhaps I should explain what your current code will do (order will vary depending on network speed):
call getPhoto(3)
construct async query to get all users (limited to top 100 by default) with success handler, i (3) passed to inner scope
return undefined (no return statement in scope)
... (when async method returns with data seconds later) ...
get the 4th item from the results (0-based array)
extract the image ID
construct a query using find() NOTE: should just use get(id) if you know the id
pass the query as a promise to the next then() handler
... (when next async method returns with data seconds later) ...
try to get the 4th items from an array that should only have one item in it
try to get properties of something that from my understanding should be null/undefined
return a string property from a promise, breaking things horribly

Categories