Kendo Grid .NET Core Template with JSON - json

I have a Kendo grid template that looks like this...
#(Html.Kendo().Grid<AuditDictionaryViewModel>()
.Name("ConferenceCourseAuditGrid")
.Columns(columns =>
{
columns.Template("#:Course.CourseName#").Title("Course Name");
columns.Template("#:IsDeleted#").Title("Is Deleted");
columns.Bound(c => c.CreatedBy).Title("Created By");
columns.Bound(c => c.CreateDateTime).Format("{0:MM/dd/yyyy hh:mm:ss tt}").Title("Create Date Time");
columns.Bound(c => c.UpdatedBy).Title("Updated By");
columns.Bound(c => c.UpdateDateTime).Format("{0:MM/dd/yyyy hh:mm:ss tt}").Title("Update Date Time");
}).Sortable()...
Where it says Course.CourseName...I'm trying to access a nested property on one of my JSON properties. The JSON that I'm getting back from the Network tab looks like this...
{
"Data": [{
"CreateDateTime": "2020-10-21T10:44:33.6716231-04:00",
"UpdateDateTime": null,
"CreatedBy": "hao.nguyen#kizan.com",
"UpdatedBy": null,
"ConferenceId": 1,
"CourseId": 1,
"IsDeleted": false,
"Course": "{\"LevelId\":5,\"Level\":null,\"CourseName\":\"Course Name...2\",\"CourseDescription\":\"Course Description...2\",\"IsRequired\":true,\"CreditHours\":2.0000,\"IsElective\":false,\"IsLocallyApproved\":false,\"TreatAsLevel5Elective\":false,\"OtherProvider\":false,\"NameProvider\":\"\",\"DisplayOrder\":2,\"IsCharterCourse\":false,\"IsNewCourse\":true,\"MandatoryTrainingTopicId\":null,\"MandatoryTrainingTopic\":null,\"MandatoryCheck\":false,\"CharterTopicCourses\":null,\"TopicCourses\":null,\"ConferenceCourses\":null,\"CreatedBy\":\"unknown\",\"UpdatedBy\":null,\"CreateDateTime\":\"2020-10-19T15:48:40.8230887\",\"UpdateDateTime\":null,\"Id\":1}"
}, {
"CreateDateTime": "2020-10-21T10:44:34.7188373-04:00",
"UpdateDateTime": null,
"CreatedBy": "hao.nguyen#kizan.com",
"UpdatedBy": null,
"ConferenceId": 1,
"CourseId": 3,
"IsDeleted": false,
"Course": "{\"LevelId\":null,\"Level\":null,\"CourseName\":\"Course Name...4\",\"CourseDescription\":\"Course Description...4\",\"IsRequired\":false,\"CreditHours\":0.5000,\"IsElective\":true,\"IsLocallyApproved\":false,\"TreatAsLevel5Elective\":false,\"OtherProvider\":false,\"NameProvider\":\"\",\"DisplayOrder\":4,\"IsCharterCourse\":false,\"IsNewCourse\":false,\"MandatoryTrainingTopicId\":null,\"MandatoryTrainingTopic\":null,\"MandatoryCheck\":false,\"CharterTopicCourses\":null,\"TopicCourses\":null,\"ConferenceCourses\":null,\"CreatedBy\":\"unknown\",\"UpdatedBy\":null,\"CreateDateTime\":\"2020-10-19T15:48:40.8230887\",\"UpdateDateTime\":null,\"Id\":3}"
}, {
"CreateDateTime": "0001-01-01T00:00:00",
"UpdateDateTime": "2020-10-22T14:46:28.5255395-04:00",
"CreatedBy": null,
"UpdatedBy": "hao.nguyen#kizan.com",
"ConferenceId": 1,
"CourseId": 2,
"IsDeleted": true,
"Course": "{\"LevelId\":null,\"Level\":null,\"CourseName\":\"Course Name...3\",\"CourseDescription\":\"Course Description...3\",\"IsRequired\":false,\"CreditHours\":3.0000,\"IsElective\":true,\"IsLocallyApproved\":false,\"TreatAsLevel5Elective\":false,\"OtherProvider\":false,\"NameProvider\":\"\",\"DisplayOrder\":3,\"IsCharterCourse\":false,\"IsNewCourse\":false,\"MandatoryTrainingTopicId\":null,\"MandatoryTrainingTopic\":null,\"MandatoryCheck\":false,\"CharterTopicCourses\":null,\"TopicCourses\":null,\"ConferenceCourses\":null,\"CreatedBy\":\"unknown\",\"UpdatedBy\":null,\"CreateDateTime\":\"2020-10-19T15:48:40.8230887\",\"UpdateDateTime\":null,\"Id\":2}"
}, {
"CreateDateTime": "2020-10-21T10:44:34.7188373",
"UpdateDateTime": "2020-10-22T14:46:29.0453815-04:00",
"CreatedBy": "hao.nguyen#kizan.com",
"UpdatedBy": "hao.nguyen#kizan.com",
"ConferenceId": 1,
"CourseId": 3,
"IsDeleted": true,
"Course": "{\"LevelId\":null,\"Level\":null,\"CourseName\":\"Course Name...4\",\"CourseDescription\":\"Course Description...4\",\"IsRequired\":false,\"CreditHours\":0.5000,\"IsElective\":true,\"IsLocallyApproved\":false,\"TreatAsLevel5Elective\":false,\"OtherProvider\":false,\"NameProvider\":\"\",\"DisplayOrder\":4,\"IsCharterCourse\":false,\"IsNewCourse\":false,\"MandatoryTrainingTopicId\":null,\"MandatoryTrainingTopic\":null,\"MandatoryCheck\":false,\"CharterTopicCourses\":null,\"TopicCourses\":null,\"ConferenceCourses\":null,\"CreatedBy\":\"unknown\",\"UpdatedBy\":null,\"CreateDateTime\":\"2020-10-19T15:48:40.8230887\",\"UpdateDateTime\":null,\"Id\":3}"
}],
"Total": 4,
"AggregateResults": null,
"Errors": null
}
The other columns show up fine, but retrieving the nested properties from Course doesn't work. I think I need a way to escape the quotes from the nested property or something in order to get that value?

The Course property seems to be an encoded JSON, try to decode it:
columns.Template("# let course = JSON.parse(data.Course); ##: course.CourseName#").Title("Course Name");
A better approach is to use DataSource's schema.parse event. Create a custom DataSource like:
#(Html.Kendo().Grid<OrderViewModel>()
.Name("grid")
.DataSource(dataSource => dataSource
.Custom()
.Schema(schema => schema
.Parse(#<text>function (data) {
data.forEach(item => item.Course = JSON.parse(item.Course));
return data;
}</text>)
)
)
)
Then you can use columns.Template("#:Course.CourseName#") on your template.

Related

Function from backend returns json object, but when received it is also an array

I'm trying to create a function that will retrieve some objects for my in a very specific format. Here's the code for that function:
pool.getConnection(function(err, connection) {
if (err) {
return res.status(500).json({
success: false,
data: err
});
}
connection.query("select cqq.* from coursequizquestions as cqq, coursequiz as cq where cqq.quiz = ? and cq.quizTitle = cqq.quiz and cq.course in (select courseUUID from courses where courseName = ?)", [quizName, courseName], function(err1, results) {
connection.release();
if (err1) {
return res.status(500).json({
success: false,
data: err1
});
}
let r = {};
for(const i in results) {
r[results[i].quizQuestion] = results[i];
}
return res.status(201).json({
success: true,
data: r
});
});
})
Where "pool" is an SQL pool object created using the mysql.createpool function. When I request this data, I'm expecting to get something that looks like this:
{
"Question 1": {
"id": 1,
"quiz": "Vue.js Introduction",
"quizQuestion": "Question 1",
"quizAnswer": null,
"dateCreated": "2021-06-17T04:00:00.000Z",
"deletedDate": null,
"videoUUID": null,
"questionScore": 50,
"questionOrder": 1,
"type": "Input"
},
"Question 2": {
"id": 2,
"quiz": "Vue.js Introduction",
"quizQuestion": "Question 2",
"quizAnswer": null,
"dateCreated": "2021-06-17T04:00:00.000Z",
"deletedDate": null,
"videoUUID": null,
"questionScore": 50,
"questionOrder": 2,
"type": "Input"
}
}
and it seems like it is exactly what I get when monitoring from the backend. When it arrives on the frontend, however, I get this:
{
"0": {
"questionOrder": 1,
"type": "input",
"quizQuestion": "0",
"questionScore": 50,
"dateCreated": "2021-06-17",
"deletedDate": null,
"videoUUID": null,
"choices": {}
},
"1": {
"questionOrder": 2,
"type": "input",
"quizQuestion": "1",
"questionScore": 50,
"dateCreated": "2021-06-17",
"deletedDate": null,
"videoUUID": null,
"choices": {}
},
"Question 1": {
"id": 1,
"quiz": "Vue.js Introduction",
"quizQuestion": "Question 1",
"quizAnswer": null,
"dateCreated": "2021-06-17T04:00:00.000Z",
"deletedDate": null,
"videoUUID": null,
"questionScore": 50,
"questionOrder": 1,
"type": "Input"
},
"Question 2": {
"id": 2,
"quiz": "Vue.js Introduction",
"quizQuestion": "Question 2",
"quizAnswer": null,
"dateCreated": "2021-06-17T04:00:00.000Z",
"deletedDate": null,
"videoUUID": null,
"questionScore": 50,
"questionOrder": 2,
"type": "Input"
}
}
There are added keys that are integers as if my object was an array. I don't see this type of output at any other endpoint. Oddly, when I log this object (in Google Chrome) the integer keys do not appear in the preview, but they do appear when I expand the entire object. Also, when I loop over this object using this code:
fetch("http://localhost:3000/api/courses/getQuestions?quizName=" + encodeURI(document.getElementById("quiz_title").value) + "&courseName=" + encodeURI(course)).then(j => j.json())
.then(j => {
console.log(j.data);
questionData = j.data;
let questionList = document.getElementById("question-list");
questionList.innerHTML = "";
for (const i in sortDict(questionData, "questionOrder")) {
makeQuestionElement(i, questionList);
}
}
then it only loops over the integer keys, essentially ignoring the portion of the output that was expected. Is there any insight as to what's happening here?
I've solved this problem - It turns out that my sortDict function was implemented incorrectly. Instead of returning an object with sorted keys, it returned a list of keys in the sorted order. The reason that the keys were populating like an array is that I was actually iterating through an array when running my loop. I've adjusted the code with this information in mind, and the problem was fixed.

How to lower levels in json?

I have a component of vuejs and my problem is that when I want a roles.name Roles works, but I don't want all JSON.
A example of JSON:
{
"id_role": 2,
"name": "Prova",
"email": "prova#prova.com",
"email_verified_at": null,
"created_at": "2021-03-01T09:39:42.000000Z",
"updated_at": "2021-03-01T09:39:42.000000Z",
"roles": [
{
"id": 2,
"name": "infomanager",
"guard_name": "web",
"created_at": "2021-03-01T09:39:42.000000Z",
"updated_at": "2021-03-01T09:39:42.000000Z",
"pivot": {
"model_id": 4,
"role_id": 2,
"model_type": "App\\Models\\User"
}
}
]
}
And this is component of vuejs:
export default {
data() {
return {
items: [],
sortBy: '',
sortDesc: false,
output: null,
// Note 'isActive' is left out and will not appear in the rendered table
fields: [
{
key: 'name',
label: 'Nom Usuari',
sortable: true
},
{
key: 'roles.name',
label: 'Nom Rols',
sortable: true
},
{
key: 'actions',
label: 'Accions'
}
],
}
},
My question is how am I down level, roles.name doesn't work.
Thank you so much!!
If I understand your question, you want to replace your roles array-of-objects to an array which holds only roles.name field.
In this case you can use flatMap method from lodash library.
Assume that your JSON is assigned into a variable called rolesJson, it will look like that:
let rolesJson = {
"id_role": 2,
"name": "Prova",
"email": "prova#prova.com",
"email_verified_at": null,
"created_at": "2021-03-01T09:39:42.000000Z",
"updated_at": "2021-03-01T09:39:42.000000Z",
"roles": [
{
"id": 2,
"name": "infomanager",
"guard_name": "web",
"created_at": "2021-03-01T09:39:42.000000Z",
"updated_at": "2021-03-01T09:39:42.000000Z",
"pivot": {
"model_id": 4,
"role_id": 2,
"model_type": "App\\Models\\User"
}
}
]
};
// create a new attribute with the flatted roles array
rolesJson.flatted_roles = _.flatMap(rolesJson.roles, el => {
return el.name;
});
// remove the original roles array
delete rolesJson.roles;

How to JSON serialize relationship collection in Laravel

I'm trying to fetch a collection of members through my model Agency (hasMany()).
members is related to an Agency through a hasMany() relationship, and I'm fetching them like so:
$members = $this->model->where("id", $agencyId)->firstOrFail()->members();
In my Member.php model class I'm implementing JSONSerializable with the following method:
public function jsonSerialize()
{
$agency = $this->agency()->first();
return [
'member_id' => $this->member_id,
'name' => $this->name(),
'surname' => $this->surname(),
'email' => $this->email(),
'active' => $this->active,
'agency' => [
'id' => $agency->id,
'name' => $agency->name,
]
];
}
However this seriazation is never being called when I try to fetch the members like so:
$members = $this->model->where("id", $agencyId)->firstOrFail()->members();
return $members->paginate(
$pageSize,
['*'],
'page',
$pageNumber
);
The response is:
"current_page": 1,
"data": [
{
"member_id": "0315c19f-8f5c-467a-97fd-a0422f5e14a5",
"user_id": "77b36a51-4b86-34be-9a76-856ca68c3a1e",
"agency_id": "d8c0cfab-686c-3b40-90ea-8bf52f07a3a0",
"active": true,
"deleted_at": null,
"created_at": "2020-04-30 15:20:38",
"updated_at": "2020-04-30 15:20:38"
},
{
"member_id": "f522914d-17cd-470d-a5d6-365930958a29",
"user_id": "994ca229-554e-3ae9-8459-24dc1479d75c",
"agency_id": "d8c0cfab-686c-3b40-90ea-8bf52f07a3a0",
"active": true,
"deleted_at": null,
"created_at": "2020-04-30 15:20:38",
"updated_at": "2020-04-30 15:20:38"
}
],
"first_page_url": "\/agency\/d8c0cfab-686c-3b40-90ea-8bf52f07a3a0\/members?page=1",
"from": 1,
"last_page": 1,
"last_page_url": "\/agency\/d8c0cfab-686c-3b40-90ea-8bf52f07a3a0\/members?page=1",
"next_page_url": null,
"path": "\/agency\/d8c0cfab-686c-3b40-90ea-8bf52f07a3a0\/members",
"per_page": 50,
"prev_page_url": null,
"to": 2,
"total": 2
}
Why are the timestamps etc. shown in the member data? Why isn't the jsonSerialize method being used?
I think Laravel uses the toArray() function for JSON serialization. You should look into Resources if you really want to control the output of your JSON.
https://laravel.com/docs/7.x/eloquent-resources

Looping and updating data in React

So quite new to React here (mostly backend and devops engineer). I need to fix a bug as the person usually responsible is not available currently.
One of the REST endpoint is formatting dates incorrectly while sending the data to the backend. The data expected from the endpoint for a PUT is
"items": [
{
"uuid": "abc7aba1-47ad-46d1-a3a5-d26ff55e4cf8",
"item_id": "21626227",
"item_description": "Test",
"item_schedule": {
"uuid": "37f8ca4c-6469-4bfb-822e-acfbc02e502e",
"start_date": "2018-12-04",
"end_date": "2018-12-06",
"interval": 3,
"unit": "days",
"occurrence": 1
"schedule_dates": [
{
"uuid": "d5b73ac5-be77-40c5-b11b-45034f70f81f",
"planned_date": "2018-12-04",
"custom": true
}
]
}
},
{
"uuid": "7abca4f4-1717-4136-aec6-3a37b4971c81",
"item_id": "21626229",
"item_description": "Test 2",
"maintenance_plan": "31001827",
"item_schedule": {
"uuid": "5de45d6e-81e8-4c86-9eb2-31c71089c876",
"start_date": null,
"end_date": null,
"interval": null,
"unit": "",
"occurrence": null,
"schedule_dates": [
{
"uuid": "da7ed2e4-053e-4f1d-80ca-2d6d258e8a08",
"planned_date": "2018-12-13",
"custom": true
}
]
}
}
]
Instead what we get for all the dates, i.e. start_date, end_date and planned_dates is (skipping all the right stuff here..)
"end_date": "2018-12-05T13:00:00.000Z",
"start_date": "2018-12-03T13:00:00.000Z"
"planned_date" : "2018-12-03T13:00:00.000Z"
When creating a new schedule for a new item, the old schedule data is incorrectly formatted.
I have tried to loop over all the items and the relevant schedule and dates and correctly format them , but doesn't seem to work.
Do I need to use map here instead of foreach?
const mapDispatchToProps = (dispatch, props) => ({
save: (value, notes) => dispatch(ItemDetailAction.saveLocal(
props.value.merge(
Map(Object.assign(
{
notes: notes.setIn([0, 'created'], undefined),
uuid: props.value.get('uuid'),
},
props.value.getIn(['item', 'type']) === 'P' && {
items: props.value
.get('items').forEach((item) => {
console.log(item.get('item_schedule'));
const start_date = item.get('item_schedule').get('start_date');
if (start_date !== '') {
const formatted_date = moment(start_date).format('YYYY-MM-DD');
//not updating the date-format below in the same array.
item.get('item_schedule').set('start_date',formatted_date);
item.setIn(['item_schedule', 'start_date'],formatted_date);
// this still prints the wrong date-format
console.log(item.get('item_schedule').get('start_date'));
}
}),
},
)),
),
true,
{
then: () => {
props.onCancel();
dispatch(actions.getItemListTable(FilterMaintenance.asParams(props.filters)));
},
}, )), });

Angular http get data and put the json object to a variable

I want to get the nested data in officeid id , code ,name ,shortname, accroym . and put it into individual variable.
How to I do that ???
My code:
{
"id": 1,
"code": "1000-001-1-01-001-001",
"name": "PEACE AND ORDER PROGRAM",
"isActive": true,
"majorFinalOutput": null,
"officeId": 1,
"office": {
"id": 1,
"code": "1-01-001",
"name": "Office of the Governor",
"shortName": "PGO",
"accronym": "PGO",
"website": null,
"email": null,
"telephone": null,
"fax": null,
"type": "1"
},
"sectorId": 1,
"sector": {
"id": 1,
"name": "General Public Services Sector",
"code": "1000",
"parentId": null,
"parent": null
},
"dateCreated": "2018-10-02T14:23:04.913",
"dateModified": null,
"createdBy": null,
"modifiedBy": null
}
getProgram() {
return this.httpClient.get('api/programs/' + idhold).subscribe((holdprogram: any[]) => {
console.log(holdprogram);
});
return this.programService.editProgram().finally( () => {
}).subscribe((holdprogram: any[]) => {
console.log(holdprogram);
console.log(holdprogram.office.id);
console.log(holdprogram.office.name);
console.log(holdprogram.office.shortname);
}, error => {
console.error(error);
},
() => {
});
}
The usual simplest way to keep a reference to a variable obtained via a request is to use a component variable :
in the component :
public export class MyComponent {
...
public office: any; // instead of using 'any', you could create an interface corresponding to the structure
...
}
in the subscribe :
.subscribe((holdprogram: any[]) => {
this.office = holdprogram.office;
console.log(this.office);
// now this.office keeps a reference of your nested variable 'office'.
},
If you need to keep a reference for it across components, it's a bit more comlicated : you could do something similar at the service level (using tap and a local variable), and you'll need to add some more "cache handling" mechanism.