How do I auto-bind properties in nested repeat-templates in polymer? - rest

I'm trying to make a simple extension of the table element. Where you can click a td, then it becomes editable, and when you edit the data it gets automatically persisted via a REST service.
Here's what I got so far
As you can see, you can click the td's and edit them, but the data does not get persisted to the other side (which is firebase in this case). That's because the data in the td's aren't bound anymore to the data-property from which they came. Can somebody tell me how I can bind them to that property again? Or any other way I can persist the data to the correct row and key?

As far as I know contenteditable change events are not supported by polymer.
You could use the onkeys to update the model manually.
In a on-* handler, you can access the named model instance using: e.target.templateInstance.model.:
<polymer-element name="x-foo">
<template>
<template repeat="{{user in users}}">
<div on-click="{{clickHandler}}">{{user.name}}</div>
</template>
</template>
<script>
Polymer('x-foo', {
clickHandler: function(e, detail, sender) {
console.log(sender.templateInstance.model.user.name);
}
});
</script>
</polymer-element>

Sevesta told me that it could only be done manually, so I gave every td extra data-attributes so I could identify them and then at the stopEditing() function I update the models manually.
See here.

Related

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

Knockout.js: Multiple ViewModel bindings on a page or a part of a page

I am wondering if it is possible to use Knockout.js's ko.applyBindings() multiple times to bind different ViewModels to one part of a page. For example, let's say I had this:
<div id="foo">...</div>
...
ko.applyBindings(new PageViewModel());
ko.applyBindings(new PartialViewModel(), $('#foo')[0]);
I am now applying two ViewModel bindings to <div id="foo>. Is this legal?
You do not want to call ko.applyBindings multiple times on the same elements. Best case, the elements will be doing more work than necessary when updating, worse case you will have multiple event handlers firing for the same element.
There are several options for handling this type of thing that are detailed here: Example of knockoutjs pattern for multi-view applications
If you really need an "island" in the middle of your content that you want to call apply bindings on later, then you can use the technique described here: http://www.knockmeout.net/2012/05/quick-tip-skip-binding.html
This is a common road block that comes when implementing JqueryMobile-SPA.
The method : ko.applyBindings(viewmode,root dom element) accepts two arguments. The second argument comes helpful when you have multiple VM's in your page.
for example :
ko.applyBindings(model1, document.getElementById("view1"));
ko.applyBindings(model2, document.getElementById("view2"));
where view1 and view2 are the root dom element for that model. For a JqueryMobile-SPA this will be the page ids for corresponding model.
The best way to do this would be use the "with" binding construct in the div that you want the partial view model to be bound. You can find it in this fiddle
<div data-bind="with: model">
<p data-bind="text: name"></p>
</div>
<div data-bind="with: anothermodel">
<p data-bind="text: name"></p>
</div>​
var model = {
name: ko.observable('somename'),
}
var anothermodel = {
name: ko.observable('someanothername'),
}
ko.applyBindings(model);​
Also check out the "with" binding documentation on the Knockout site, to look at an AJAX callback - partial binding scenario.
My english is very bad.... =)
I use Sammy to load partial views, and Knockout to bind the Model, I try use ko.cleanNode but clean all my bindings, all DOM nodes has changed when has a bind, a property __ko__ is aggregated, then i removed that property with this code, and works !!, '#main' is my node.
var dom = dom || $("#main")[0];
for (var i in dom) {
if (i.substr(0, 6) == "__ko__") {
delete (dom[i]);
break;
}
}
after use Ggle translator:
I use Sammy for the load of partial views, and Knockout for the bind the Model, I try to use ko.cleanNode but clean all my bindings, all DOM nodes has changed when they has a bind, a property ko is aggregated, then i removed that property with this code, and works !!, '#main' is my node.

jQuery on() click event handler with dynamic data crashing

Here's a simplified example of what I'm trying to achieve: http://jsfiddle.net/easLc/
HTML
<div class="bar">
<div class="apple"> apple</div>
<div class="banana"> banana</div>
<div class="citrus"> citrus </div>
</div>
jQuery
function showAlert(event) {
inventory = event.data.inventory;
alert(inventory);
}
fruits = ["apple", "banana", "citrus"];
inventory = [13, 45, 99];
for (i in fruits) {
$(".bar ."+fruits[i]).on("click", {inventory:inventory[i]},showAlert);
}
The inventory data I'm passing to the handler is dynamic, not static like the example. I'm getting the inventory data from asynchronous calls. After each time the inventory data is updated, I want to pass this data to the handler instead of have the handler get that information again.
What I'm noticing is on some clicks, the handler (I think) is crashing my browser. Am I creating too many handlers inadvertently? How do I see what handlers were created? Or what happens during the click event? I tried adding some console.log to the handler but I don't see them in the console.
Thanks!
Try
$(".bar ."+fruits[i]).off('click',showAlert).on("click", {inventory:inventory[i]},showAlert);
This will remove the previously bound event and rebind it... But it is hard to determine if it is the real source of the problem. You can add a console.log('text') in showAlert to see if it is being called more than once.
You can prevent multiple bindings by adding some sort of data to the element once it's been bound (a clean way would be a class, but meta-data may be preferred by standards):
$(".bar ." + fruits[i]).not(".bound").on('click', {...}).addClass('bound');

delete item from a dojo.store.jsonrest

I started with this tutorial http://dojotoolkit.org/documentation/tutorials/1.6/store_driven_tree/
after setting up my ServerSide Restfull Service everything is working so far. I made a contextmenu for the tree by:
<ul dojoType="dijit.Menu" id="contextMenu" style="display: none;">
<li dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconDelete" onclick="pages.remove(tn.item.id);">delete page</li>
</ul>
<script type="dojo/connect">
var menu = dijit.byId("contextMenu");
menu.bindDomNode(this.domNode);
dojo.connect(menu, "_openMyself", this, function(e){
// get a hold of, and log out, the tree node that was the source of this open event
tn = dijit.getEnclosingWidget(e.target);
// contrived condition: disable all menu items except the "New Page" item
dojo.forEach(menu.getChildren(), function(child){
if(child.label != "Neue Seite")
{
child.set('disabled', typeof tn.item == 'undefined');
}
});
});
</script>
Now I know on wich node the user made the right click for the contextmenu and delete it with "pages.remove(tn.item.id);" from the Database. To notify the tree I´m overriding the remove function:
remove: function(objectId){
this.onDelete({id: objectId});
return dojo.store.JsonRest.prototype.remove.apply(this, arguments);
}
Everything works as expected but if im now doing some other things with the items in the tree like drag n drop an item to the root i was deleting a child before. The tree isn't showing it correctly anymore. I think the remove method of the store only sends the DELETE query to the Server but don't removes the item from the store. How can i get the array of the items in store to check and maybe to delete items?
The dijit.Tree is a presentation of an underlying dojo.data model, and any changes that you want to make to the tree really need to be done to the underlying data store. See the description here: http://dojotoolkit.org/reference-guide/dijit/Tree.html#dijit-tree So, instead of overriding the remove function, you should instead use the dojo.data API to modify the store, and then rerender the tree to reflect the changes. The best source for looking at the various methods available is in the dojo nightly files. Specifically, the dojo.data files are here: http://archive.dojotoolkit.org/nightly/dojotoolkit/dojo/data/
var item = tree.fetchItemByIdentity("selectedItem"); //find the item you want to remove
store.deleteItem(item); //delete the item from the data store
store.save(); //save the change made to the store

Jquery Selector Multiple Classes (this)

I have a page that lists content that are contained in a div with a class ad-container. in that container there is a hidden div with the class ad-contact. on the hover of the ad class i want to animate the display of ad-info. since there are multiple ads on a paticular page, i want only the ad-info of the currently hovered ad-container to slide in. my problem is that since there are more than 10 ads a page when you hover over any of the ads, all of the ads-contact divs slideDown and not the one you are hovering over.
$(document).ready(function() {
$('.ad-container').hover(
function(){
$(".ad-contact").slideDown(1000);
},
function(){
$(".ad-contact").slideUp(1000);
});
});
i think, (this) is used here but im not sure. and this would really shed the light for me.
<div class="ad-container">
<div class="ad-title">title<span class="ad-title-img">(pic)</span></div>
<div class="ad-description">texttext</div>
<div class="ad-contact" style="display:none">contact poster</div>
<div class="ad-sellerinfo" style="display:none">* Verified ***-****<br />
Paid Member</div>
</div>
The jQuery constructor accepts a 2nd parameter which can be used to override the context of the selection. Something like this should work:
$(document).ready(function() {
$('.ad-container').hover(
function(){
$(".ad-contact", this).slideDown(1000);
},
function(){
$(".ad-contact", this).slideUp(1000);
});
});
Also, worth mentioning, $(".ad-contact", this) is internally converted into: $(this).find(".ad-contact") so you can use this one instead, it might be slightly faster.
You could use the .children() selector:
$(this).children(".ad-contact").slideDown(1000);
This way you will only act on the class ad-contact if its a child of the object in context (which is the object currently being hovered)
See a working demo here
You should use event to handle this,
First you need like
ad-container.hover(function(event){
event.target.children();
})
and then this.show().delay(1000).hide();
the code sample provide may not work when copy paste you have to write your own code in editor.