Kendo UI Grid Data Disappears on Popup Edit Cancel - mvvm

I am trying to figure out why the data in my grid disappears when i click the edit button and then immediately close out the popup.
I am trying to use the value binding features of Kendo UI and i cant seem to understand why they are being removed.
Here is a jsfiddle of what i am talking about.
http://jsfiddle.net/JDMp8/13/
<div id="gridData">
<div
data-editable="popup"
data-role="grid"
data-bind="source: test"
data-columns="[
{field: 'ID', title: 'test'},
{command: ['edit', 'destroy'], title: 'test'}]"/>
var gridData = kendo.observable({
test:[
{ID: 1, Name: "Record 1"},
{ID: 2, Name: "Record 2"},
{ID: 3, Name: "Record 3"},
{ID: 4, Name: "Record 4"},
{ID: 5, Name: "Record 5"},
{ID: 6, Name: "Record 6"},
{ID: 7, Name: "Record 7"},
{ID: 8, Name: "Record 8"},
{ID: 9, Name: "Record 9"},
]
});
kendo.bind($('#gridData'), gridData);
I understand that i can use a data source rather than observable, but the actual view model i am using gets its data from the database and is nested a few layers down. The grid binds just fine but when i try to cancel or close the window it just gets removed.
How can i configure the value binding to prevent the results from being cleared?

It seems to be upset that the DataSource it is bound to (internally it converts your array to a DataSource) doesn't have a model defined. It uses the types defined on the model to help pick the correct editor.
Try this code:
var gridData = kendo.observable({
test: new kendo.data.DataSource({
data: [
{ID: 1, Name: "Record 1"},
{ID: 2, Name: "Record 2"},
{ID: 3, Name: "Record 3"},
{ID: 4, Name: "Record 4"},
{ID: 5, Name: "Record 5"},
{ID: 6, Name: "Record 6"},
{ID: 7, Name: "Record 7"},
{ID: 8, Name: "Record 8"},
{ID: 9, Name: "Record 9"},
],
model: {
fields: {
ID: { type: "number" },
Name: { type: "string" }
}
}
})
});
// Bind the view model to the personFields element.
kendo.bind($('#gridData'), gridData);

To answer the item in the comments re what to do with server side objects being called. I have used the following to bind to a js object that is called via the server.In the case below referralViewModel.dropDownItems.Statuses is an object that it generated from the server via a controller.
<div
id=myGridId
data-role="grid"
data-scrollable="true"
data-bind="source: myArray"
data-editable="{mode: 'popup'}"
data-toolbar="['create']"
data-columns="[
{command:['edit'], width:50},
{ 'field': 'Text', 'width': 200, 'title': 'Text' },
{ 'field': 'Value', 'width': 200, 'title': 'Value' },
]"
style="width: 100%; height: auto"></div>
Using the following script:
<script>
myObservable = new kendo.observable({
myArray: new kendo.data.DataSource({
data: referralViewModel.dropDownItems.Statuses, //bind to root level view model
schema:{
model: {
id:"Value", //primary key
fields: {
Value: { type: "string" },
Text: { type: "string" }
},
}
}
})
});
kendo.bind($("#myGridId"), myObservable);

Related

Multiple bars with same category name show differently based on array of arrays or array of objects

I noticed that using
option = {
xAxis: {
type: 'category',
},
yAxis: {
type: 'value'
},
series: [ {
type: 'bar',
data: [
{ name: 'Sun', value: 50 },
{ name: 'Sun', value: 80 },
{ name: 'Mon', value: 100 }
]
}]
}
There are two bars with category as 'Sun'. But if I use
option = {
xAxis: {
type: 'category',
},
yAxis: {
type: 'value'
},
series: [{
type: 'bar',
data: [
['Sun',50],
['Sun',80],
['Mon',100]
]
}]
}
I see only one bar for 'Sun' with both data elements overlapping. Why does it work with array of objects differently? Also, if instead of using inline data, if I use dataset, then both array of arrays and array of objects behave the same where there is only one bar with overlap.
The reason I am looking for clarity on this is, I have a visualMap with a different attribute for color which makes the data repeat. I am trying to figure out if I need to create separate series or use the same series.
In general is bad idea to naming data points the same name. Strange that the data in the first case did not merge... If you need make the group then in the Echarts it's named stack. For the stack you can use the same name and it will be joined into one group.
VisualMap usually the global option and affects all series but you can limit with seriesIndex.
var myChart = echarts.init(document.getElementById('main'));
var option = {
xAxis: {
data: ["Cat1", "Cat2", "Cat3", "Cat4", "Cat5", "Cat6"]
},
visualMap: {
type: 'continuous',
range: [0, 70],
seriesIndex: 2,
color: ['green', 'blue', 'red'],
},
yAxis: {},
series: [{
name: 'Series1',
stack: 'group1',
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
color: 'lightgray'
}, {
name: 'Series2',
stack: 'group1',
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
color: 'gray'
}, {
name: 'Series3',
stack: 'group2',
type: 'bar',
data: [50, 20, 70, 10, 60, 40],
}]
};
myChart.setOption(option);
<script src="https://cdn.jsdelivr.net/npm/echarts#4.9.0/dist/echarts.min.js"></script>
<div id="main" style="width: 600px;height:400px;"></div>

How to color every bar in google timeline chart?

I have read some other answers here and accordingly added the role property but it did not work.
<Chart
width={'500px'}
height={'300px'}
chartType="Timeline"
loader={<div>Loading Chart</div>}
data={[
[
{ type: 'string', id: 'President' },
{ type: 'date', id: 'Start' },
{ type: 'date', id: 'End' },
{type: 'string', role: 'style'}
],
['Washington', new Date(1789, 3, 30), new Date(1797, 2, 4), 'gold'],
['Adams', new Date(1797, 2, 4), new Date(1801, 2, 4), 'color: #ccc'],
['Jefferson', new Date(1801, 2, 4), new Date(1809, 2, 4), 'gold'],
]}
options={{
showRowNumber: true,
}}
rootProps={{ 'data-testid': '1' }}
/>
refer: https://react-google-charts.com/timeline-chart
on the timeline chart, the style role will only work when used as the third column.
so you will also need to add the second column for bar label.
but you can use null values for that column, if needed...
<Chart
width={'500px'}
height={'300px'}
chartType="Timeline"
loader={<div>Loading Chart</div>}
data={[
[
{ type: 'string', id: 'President' },
{ type: 'string', id: 'Bar' }, // <-- add bar label here...
{ type: 'string', role: 'style' }, // <-- add style role here...
{ type: 'date', id: 'Start' },
{ type: 'date', id: 'End' }
],
['Washington', null, 'gold', new Date(1789, 3, 30), new Date(1797, 2, 4)],
['Adams', null, '#ccc', new Date(1797, 2, 4), new Date(1801, 2, 4)],
['Jefferson', null, 'gold', new Date(1801, 2, 4), new Date(1809, 2, 4)],
]}
options={{
showRowNumber: true,
}}
rootProps={{ 'data-testid': '1' }}
/>
I got it! I sorted the bars according the role attribute.
I used the role property in data structure.
const data = [ [ { type: "string", id: "Phases" },{ type: "string", id: "Name" }, { type: 'string', role: 'style' }, { type: "date", id: "Start" }, { type: "date", id: "End" } ]];
<Chart chartType="Timeline" data={[...data, ...firstArray, ...secondArray]} width="100%" height={setChartHeight((firstArray.length+secondArray))} options={{ timeline: { } }} />
enter image description here
This is my second answer on Stackoverflow. I still don't understand how to indent the code in the answer.

Merge state with array of objects ignoring duplicates in React Native Redux

I have an initial state like this:
export const INITIAL_STATE = Immutable({
payload: []
})
When I dispatch the request action, it returns an array of objects, something like this:
[
{id: 1, name: 'userA'},
{id: 2, name: 'userB'},
{id: 3, name: 'userC'}
]
So, when I try to refresh the state, I merge the existing payload with the new one I get from my server:
export const success = (state, { payload }) => {
const newPayload = state.payload.concat(payload)
return state.merge({ payload: newPayload })
}
This makes my new state end up something like this:
[
{id: 1, name: 'userA'},
{id: 2, name: 'userB'},
{id: 3, name: 'userC'},
{id: 4, name: 'userD'},
{id: 5, name: 'userE'},
{id: 6, name: 'userF'}
]
So, that part works, but, if I call again my request action, the state is getting populated with duplicated data, like this:
[
{id: 1, name: 'userA'},
{id: 2, name: 'userB'},
{id: 3, name: 'userC'},
{id: 4, name: 'userD'},
{id: 5, name: 'userE'},
{id: 6, name: 'userF'},
{id: 1, name: 'userA'}, // <== duplicated data
{id: 2, name: 'userB'}, // <== duplicated data
{id: 3, name: 'userC'} // <== duplicated data
]
What I need is that if I call the request action, and the same data is returned from the server - in this case ids 1, 2 and 3 - then for state.merge to just leave the payload as it is or update them with new values if that's the case, so if user with id 2 updated his name in the server to newUserB then my new state would be like:
[
{id: 1, name: 'userA'},
{id: 2, name: 'newUserB'},
{id: 3, name: 'userC'},
{id: 4, name: 'userD'},
{id: 5, name: 'userE'},
{id: 6, name: 'userF'}
]
instead of this:
[
{id: 1, name: 'userA'},
{id: 2, name: 'userB'},
{id: 3, name: 'userC'},
{id: 4, name: 'userD'},
{id: 5, name: 'userE'},
{id: 6, name: 'userF'},
{id: 1, name: 'userA'},
{id: 2, name: 'newUserB'},
{id: 3, name: 'userC'}
]
I have tried using state.merge({ payload: newPayload }, {deep: true}) but it's not working the way I expect, I also tried state.merge({ payload }) and the same.
Anyone knows how to accomplish this?
Firstly merge the two arrays and then filter only unique items.
export const success = (state, { payload }) => {
const newArr = state.payload.concat(payload)
const idPositions = newArr.map(el => el.id)
const newPayload = newArr.filter((item, pos, arr) => {
return idPositions.indexOf(item.id) == pos;
})
return state.merge({ payload: newPayload })
}

In Sails.js v0.10 after populating data as a value i get [Getter/Setter]

After populating data i get result not as expected.
Example:
//User.js Model
module.exports = {
attributes: {
//"id" attribute is here primary key by default
schools: { collection: 'School', via: 'id' },
name: { type: 'String', trim: true, required: true }
}
}
And this is my School.js
//School.js Model
module.exports = {
attributes: {
//"id" attribute is here primary key by default
name: { type: 'String', trim: true, required: true },
}
}
My User entity data looks like this:
//User document in MongoDB
{
_id: 1,
name: "Foo",
schools: [1,2,3]
}
My School entity data looks like this:
//School documents in MongoDB
{
_id: 1,
name: "School 1"
}
{
_id: 2,
name: "School 2"
}
{
_id: 3,
name: "School 3"
}
Now i want to populate the schools. I do it like this:
User.find().populate("schools").exec(function(err, res){ console.log(res[0]) });
And this is what i get as a result:
{
schools: [Getter/Setter],
name: "Foo",
id: 1
}
Expected:
{
schools: [
{id: 1, name: "School 1"},
{id: 2, name: "School 2"},
{id: 3, name: "School 3"}
],
name: "Foo",
id: 1
}
How can i get expected results?
I use MongoDB as data storage.
Versions:
Sails.js: v0.10.0-rc5
Waterline: v0.10.0-rc7
sails-mongo: 0.10.0-rc2
Those are the expected results when using console.log! If you want to see the expanded object, do:
console.log(res[0].toObject());

How to redirect to a nested dynamic segments in EMberjs

If we have several books,each books contains several chapters and each chapter contains several pages.
In an App,
when user navigate to
"/home"
list all the books,clicking a book(eg:book_1) will directly "linkTo"
"/book_1/chapter_1/page_1"
show the content of "chapter_1/page_1" within the selected book.
I am now trying to use the "redirect" hook,but I am confused with these:
1,How to sent muti params to a redirect hook;
2,How to update the URL correctly after redirecting?
3,What is the "Ember way" to do this?
_BOOK MODEL__
App.Book = DS.Model.extend({
name: DS.attr('string'),
chapters: DS.hasMany('chapter',{async:true}),
color: DS.attr('')
});
App.Chapter = DS.Model.extend({
name: DS.attr('string'),
author: DS.attr(''),
pages: DS.hasMany('page',{async:true})
});
App.Page = DS.Model.extend({
name: DS.attr('string'),
});
App.Book.FIXTURES = [
{
id: 1,
name: 'book1',
color: 'red',
chapters: [1,2]
},
{
id: 2,
name: 'book2',
color: 'blue',
chapters: [3,4]
}
];
App.Chapter.FIXTURES = [
{
id: 1,
name: 'Chapter1',
author: 'jhon',
pages:[1,2]
},
{
id: 2,
name: 'Chapter2',
author: 'jhon',
pages:[3,4]
},
{
id: 3,
name: 'Chapter3',
author: 'peter',
pages:[5,6]
},
{
id: 4,
name: 'Chapter4',
author: 'tom',
pages:[7,8]
}
];
App.Page.FIXTURES = [
{
id: 1,
name: 'page1',
},
{
id: 2,
name: 'page2',
},
{
id: 3,
name: 'page3',
},
{
id: 4,
name: 'page4',
},
{
id: 5,
name: 'page5',
},
{
id: 6,
name: 'page6',
},
{
id: 7,
name: 'page7',
},
{
id: 8,
name: 'page8',
}
];
redirect is deprecated, use the afterModel hook. I'm sending in ids of 1 and 1 to the chapter and page route, which should hit their model hooks. How is your data separated, does the book model have all the necessary info?
http://emberjs.jsbin.com/uDiLIkij/6/edit
afterModel: function(model, transition){
console.log(transition.targetName);
if(transition.targetName=='book.index'){
var self = this;
model.get('chapters').then(function(chs){
var ch = chs.get('firstObject');
ch.get('pages').then(function(pages){
var page = pages.get('firstObject');
self.transitionTo('page', model, ch, page);
});
});
transition.abort();
}
},