Rebinding a detail view to a model with kendo UI - mvvm

I have a list view containing basic info about a set of tasks and I want to bind a detail view to the model object for an item when an item from the list is selected ...
http://jsfiddle.net/g2wYX/
I've been trying to use the change event of the grid ...
change: function (arg) {
var grid = $("#taskGrid").data("kendoGrid");
var selectedItem = grid.dataItem(grid.select());
kendo.bind("#taskDetail", selectedItem);
}
For some reason I can't seem to figure out the model binding on the detail view.
Does anyone have any ideas on how I can do this?

The binding is just simple as binding to any of the View, the only difference is that you have to place the Detail template inside a < scripts /> tag with type set as text/x-kendo-template. I have updated your fiddle example to what I have understood you require.
<script id="javascriptTemplate" type="text/x-kendo-template">
and provide the detail template link to the Grid as below:
detailTemplate: kendo.template($("#javascriptTemplate").html()),
Let me know if the solution is not what you desired or you are confused in any code statement.
Question Fiddle Solution
EDIT:
Updated the fiddle Solution as per your requirement,have a look and let me if that is as per your requirement.
The only change that is required in your code is just change the data-bind from value to html
Updated Solution

Related

Add to the beginning of Reactive Forms Array Angular

Please see the relevant plunker
https://plnkr.co/edit/f0BxpinhuqVz8o6IIFaL?p=preview
stack overflow makes you put code if a plunker is linked
but it is too much code to copy paste here it would just
look messy so I a am putting this comment instead.
If you run this and then click the add button a new entry is added to the array, but the form view does not reflect the forms state, instead the first entry is duplicated and the last entry is gone.
If anyone has any ideas or guides as to what I am doing wrong I would be very grateful as I have been pretty stuck on a seemingly easy task.
I tried to follow the official Angular Reactive Forms guide as close as possible to build this example.
Seems like Angular has trouble tracking the index of your objects in your formArray. This can be solved by using trackBy. Add it to your iteration with function:
<div *ngFor="let detail of detailArray.controls; let i=index; trackBy:trackByFn" [formGroupName]="i">
and in component:
trackByFn(index: any, item: any) {
return index;
}
Your PLUNKER

Best practice to lazy load data on tab click

Within the onBeforeRendering() function of a view how should I determine if a specific node is present in the model and modify the model to include the node if not? This question is about lazy loading of data to the model for data that will be infrequently accessed by users but would have a performance penalty if loaded with initial model data.
My use case has a list page leading to a detail page for whatever item in the list the use clicks. On the detail page is a set of tabs which expose sub-details related to the selected detail. Specifically a long text description of a the brief for a task.
The tab control leads via manifest.json style routing to display a view in the tabs content area.
This is my current working code which is within the onBeforeRendering event of the view controller:
onBeforeRendering: function(oEvent){
var sPath = this.getView().getBindingContext("Projects").getPath(); // something like /task/6
console.log('Path='+sPath)
var oModel = this.getView().getModel("Projects");
var oTask = oModel.getProperty(sPath + "/brief");
if (oTask) { // looks like /brief exists so must already have loaded the brief
// nothing to do
console.log('Use existing data')
}
else { // /brief not yet present so we need to load it up
console.log('Load new data')
oModel.setProperty(sPath + "/brief", "This is the brief...") // replace with loaddata() from server, use attachRequestCompleted to call function to modify model.
}}
Question - is this the correct approach?
Edit: Based on discussion in this question I modified my code to use an event that fires per display of the view. onBeforeRendering turned out to run without much apparent predictability - which I am sure it has but in any case I wanted a one-per-display event. Also, I fleshed out the code further but retained the basic structure and it appears to do what I wanted.
This is a valid approach. But you should think aboute following use case: What happens if the data you loaded have been changed at the backend? The JSONModel does not give you any support here as it acts dumb data store only.

Kendo UI Hierarchical datagrid - How to access root viewModel from detail grid editor template MVVM

I have a grid within a grid, where parent grid is constructed in MVVM, child grid initialized on its data-detail-init http://jsbin.com/kuvejuw
<div data-role="grid"
data-columns="[
{ 'field': 'FirstName'},
{ 'field': 'LastName'}
]"
data-bind="source: dataSource"
data-detail-init="viewModel.detailInit"
>
</div>
If have a custom property (e.g. Text here) on the viewModel, and in the popup editor of the child grid, I would like to bind to this property. So e.g. in more complex scenarios I can populate a dropdownlist with a range of values by having an array (or observable array) on the viewModel.
var viewModel = kendo.observable({
dataSource: new kendo.data.DataSource ... // everything works here,
detailInit: detailInit,
Text: "This text should be displayed in editor in detail's grid",
});
kendo.bind(document.body, viewModel);
The problem is that this property (or overall viewModel) is not detectable in the template of the detail grid's editor:
function detailInit(e){
...
editable: {
mode: "popup",
template: kendo.template($("#child-editor-template").html())
}
...
}
Template is built like this:
<script type="text/x-kendo-template" id="child-editor-template">
<span data-bind="text: Text"></span>
</script>
but I also tried data-bind="text:viewModel.Text". I tried various solutions, setting the Text property on viewModel in detailGrid's edit event, or setting it on viewModel bind, but it does not work with this jsBin (3.2016 version).
Now funny thing is that I actually able able to access this property with a 2015v3 Kendo UI in my local project, but I cannot replicate it in this jsBin.
In my local project though I still cannot access the events in ViewModel e.g. I could do text: Text, but could not do events: {select: onSelect}.
Accessing the events would be ultimately the reason for asking this question once this thing is sorted, I'm looking for some hints to understand what's going on, if I'm expecting too much from mvvm.
EDIT:
I'm looking forward to this type of functionality that would be enabled in the popup editor of the child grid http://jsbin.com/canomux
Try like this,
I just make changes in your template,
<script type="text/x-kendo-template" id="child-editor-template">
<input name="ShipCountry"/>
</script>
http://jsbin.com/levenacari/edit?html,js,output
It seems the way of retrieving the data from API was somewhat unexpected, so with change of:
options.success(e.data.Orders.results.toJSON());
to
options.success(e.data.Orders.results);
the binding of text works.
With the events binding it is not working - it seems it's not something to do with detailGrid but in general with grid, which is described
here

Waiting for sap.ui.table.Table rendered after bound model has changed

I have sap.ui.table.Table which rows are bound to an JSONModel.
var oListModel = new sap.ui.model.json.JSONModel();
//oTable created here (sap.ui.table.Table)
oTable.setModel(oListModel);
oTable.bindRows("/");
When the table is rendered, i.e. the DOM is created for this table, i need to reference to the DOM to pass the DOM elements (table rows) to a library which will make them draggable.
My problem is: How do i know when the DOM for the table is created after the model has been changed and the table is rerendered? I didnt find any listener. The view controller's listener onAfterRendering() didn't help me.
The model is filled with data after a XMLHTTPRequest is successful. When i set the model in the success handler of the xht request and try to access the DOM elments directly afterwards they don't exist yet.
Thank you for your help!
You can add an event delegate
var oMyTable = new sap.ui.table.Table();
oMyTable.addEventDelegate({
onAfterRendering: function() {
$table = this.getDomRef() ....
}
});
a better way is to extend the control see Using addDelegate to extend a control to use third party functionality
UPDATE
the example in that blog doesn't work anymore fixed here
I had a similar issue recently where i had to access an element after a smartform (where the element is present) rendered onto the view. I posted my query here as well as my final solution (based on the accepted answer of #Dopedev). I am using XML views - including nested XML views - here however and the onAfterRendering didn't help for me as well.
I guess you could look at this solution - like it's mentioned in the accepted answer, it may not be an optimal solution, but it sure works. In my case there is not much of a performance issue with the binding of the DOMNodeInserted since it is being called in the onAfterRendering of the nested view that consists of only the smartform with an immediate unbinding upon finding.
The condition if (id === "yourtableid") { } should be enough to identify and pass on. Since you have a table and thus several child nodes, unbinding is imperative at this point.
Mutation Observer is the preferred method but i guess you may need to check the browser compatibility table at the end of the page to see if it matches your requirements. There is an example here. I have used Mutation Observer (outside of a SAPUI5/openUI5 environment) earlier and found it very convenient(and performant) to listen to DOM insert events. In fact the sap.ui.dt package consists of MutationObserver.js

Knockout 2: How to delay observable object.

Hi i have a problem in knockout 2: I want to do late binding because i am adding data-bind via jQuery
$("#button1").on ("click", function() {
lateBinding = $("#lateBindingElem);
if (lateBinding.length) {
lateBinding.attr("data-bind", "text: obs");
}
}
});
late binding is an html generated on the fly.
I have a view model created already call MyViewModel.
I want to add another attribute or another observable (could be computed or uncomputed) on the fly to existing view model? How would i do this?
Hopefully you have already found an answer elsewhere (7 months ago :D) but since I stumbled upon this question in hopes to find a solution to a similar problem, I might as well and try to give a sort-of-an-answer for anyone else looking into it. This won't let you manipulate the binding for elements you already have bound to a model but allow you to pause binding at given points and bind newly created elements to your current or a different viewmodel.
Built on Ryan Niemeyers great article about how to stop bindings and accompanying jsfiddle example is a little demo which adds new input elements to dom and binds them to different viewmodels.
Since you can only bind a section of your dom once you need to stop the downward binding at some point using a custom binding..
ko.bindingHandlers.stopBinding = {
init: function() {
return { controlsDescendantBindings: true };
}
};
assign it to a wrapper
<div data-bind="stopBinding: true" id="addNewContentHere"></div>
and insert your new elements
function addInput(){
var data=$('<input type="input" data-bind="value: newInput" />');
ko.applyBindings(MyViewModel, data[0]);
$('#addNewContentHere').append(data);
};
hope it is of some use :)