Bind a value from a polymer element to the parent page - binding

I have made a simple ploymer element, i need to change an input value on the page that contains that polymer element.
<html>
<head>
<script src="../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="dial-buttons/dial-buttons.html">
</head>
<body>
<input type="text" name="dial-number" id="num-input" />
<paper-material elevation="1">
<dial-buttons></dial-buttons>
</paper-material>
</body>
</html>
And here is the element code:
<dom-module id="dial-buttons">
<template>
<div on-click="handleClick" data-args="0, num-input">
<p>0</p>
<span>+</span>
<paper-ripple></paper-ripple>
</div>
</template>
<script>
Polymer({
is: 'dial-buttons',
handleClick: function(e) {
var args = Polymer.dom(e).path[1].getAttribute('data-args').split(',');
document.getElementById(args[1]).value = args[0]; //Here is the issue!
}
});
</script>
</dom-module>
What im trying to achieve here is, when a click event on the "dial-buttons" element is fierd, the input value on the parent page should get the value sent from this child element.

Checked that part in the documentation.
You create a property which is called let's say myVar, you set notify to true (just like the first example). Inside your function set this.myVar to the value you want and it should be reflected to your attribute which you bind to in your parent element.

Related

Why doesn't the model get updated?

I'm going through the angular dart tutorials and I tried to make a list of items and when one is clicked fill an input with the clicked item's text. This works OK until I modify the text in the input. After that clicking another item in the list does not update the text in the input field (before it did), and neither gets the item in the list modified.
My starting point the 2 tutorial, but trying to combine it with some input as in the first one.
My html file:
<!DOCTYPE html>
<html ng-app>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test</title>
</head>
<body>
<div data-list>
<ul>
<li ng-repeat="data in ctrl.dataList" ng-click="ctrl.selectData(data)">{{data.text}}</li>
</ul>
<input type="text" value="{{ctrl.selected.text}}">
</div>
<script type="application/dart" src="spa.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
My dart file:
import 'package:angular/angular.dart';
#NgController(
selector: '[data-list]',
publishAs: 'ctrl'
)
class DataController{
DataValue selected;
List<DataValue> dataList = [new DataValue("uno"), new DataValue("dos"), new DataValue("tres")];
void selectData(DataValue selected){
this.selected = selected;
}
}
class DataValue{
#NgTwoWay('text')//Also tried without this. Same result
String text;
DataValue(this.text);
}
class DataAppModule extends Module{
DataAppModule(){
type(DataController);
}
}
void main(){
ngBootstrap(module: new DataAppModule());
}
Any idea what I'm doing wrong?
The desired behavior should be:
the items in the list are displayed
when any of them is click the input field gets updated
when editing the input field's value the currently selected item of the list gets updated with the new text
At any moment clicking an item updates the value of the input file
Use the input element with the ng-model directive to have a two-way binding:
...
<input type="text" ng-model="ctrl.selected.text">
...
The #NgTwoWay annotation is only used in components or controllers, used in class DataValue it is ignored.

Rendering a content tag as part of a template in polymer and dart

I wish to make a generic list using polymer and dart. I am extending the UL element to do so. I want to place template variables within the content of this custom element.
<ul is="data-ul">
<li>{{item['first_name']}}</li>
</ul>
The custom element
<polymer-element name="data-ul" extends="ul">
<template repeat="{{item in items}}">
<content></content>
</template>
<script type="application/dart" src="data-ul.dart"></script>
</polymer-element>
I was expecting the template variable to be interpolated however it simply gets outputted to the DOM as is. How do I output the content tag to be rendered as a template and not just directly outputted?
Unfortunately, there are two issues here.
<content> cannot be used like this. It's a placeholder for rendering light DOM nodes at specific locations in the Shadow DOM. The first <content> that selects nodes, wins [1]. Stamping out a bunch like you're doing, while very intuitive, won't work as expected.
You're mixing the internal world of Polymer with the external world outside the element. What this really means is that bindings (e.g. {{}}) only work in the context of <polymer-element>.
One thing you can do is create a copy of the distributed light DOM children as the items property of your element. In JavaScript this looks like:
<template repeat="{{item in items}}">
<li>{{item['first_name']}}</li>
</template>
<content id="content" select="li"></content>
<script>
Polymer('data-ul', {
ready: function() {
this.items = this.$.content.getDistributedNodes();
}
});
</script>
Note: The only reason I've used <content select="li"> is to insure the element only takes in <li> nodes. If you're not worried about users using other types of elements, just use this.items = [].slice.call(this.children);.
To do that you should override the parseDeclaration method. This method is in charge of parsing/creating the needed html that will be bound. For example, let say that you have next template
<polymer-element name="data-ul" extends="ul" attributes="items">
<template>
<template repeat="{{item in items}}" ref="itemTemplate"></template> <!-- this is the replacement of content tag -->
</template>
<script type="application/dart" src="data-ul.dart"></script>
</polymer-element>
Or if you want to have some default elements:
<polymer-element name="data-ul" extends="ul" attributes="items">
<template>
<template repeat="{{item in items}}">
<!-- Def elements -->
<template bind="{{item}}" ref="itemTemplate"></template> <!-- this is the replacement of content tag -->
<!-- Def elements -->
</template>
</template>
<script type="application/dart" src="data-ul.dart"></script>
</polymer-element>
then you should have next class:
#CustomTag('data-ul')
class DataUl extends LiElement with Polymer, Observable {
DataUl.created() : super.created();
#published List items;
void parseDeclaration(Element elementElement) {
// We need to remove previous template from element.templateContent
// in that way it no continues adding a new content every time that we instantiate
// this component.
var previousTemplate = element.templateContent.querySelector('template#item');
if(previousTemplate != null)
previousTemplate.remove();
var t = this.querySelector('#itemTemplate'); // Gets the template with id itemTemplate from the content html
if(t != null) // if not null
element.templateContent.append(t); // append itemTemplate to element.templateContent
else
element.templateContent.append(new TemplateElement()..id='itemTemplate'); //if no template is added append an empty template to avoid errors
super.parseDeclaration(elementElement); // call super
}
}
And finally use the custom element as follow:
<ul is="data-ul" items="{{[{'first_name': 'jay'}, {'first_name': 'joy'}]}}">
<template id="itemTemplate">
<li>{{item['first_name']}}</li>
</template>
</ul>

taphold not working with dyanmatically created listview in phonegap Android

I have an listview which fect the data from the local database. And I want to add and taphold event on the list items so i uses taphold example from this site http://www.raymondcamden.com/index.cfm/2012/5/23/Context-Menu-Example-with-jQuery-Mobile but when run this code on emulator its working fine but when i tried to implement it into code which i'm usign its not working properly it giving an alert thats its in Taphold event but doesn't create a sampledialog box here the code which I am using:
function createlist(){
alert("I am in create list");
db.transaction(function(tx){
tx.executeSql(select_nameUserDetails,[],function(tx,results){
$('#name').empty();
alert("from list "+results.rows.length);
if(results.rows.length>0)
{
for(var i=0;i<results.rows.length;i++)
{
alert(i);
$('#name').append('<li><p class="namelist" id="s'+i+'" onclick="selectname('+results.rows.item(i).id+')">'+results.rows.item(i).frist_name+'</p></li');
temp_id=results.rows.item(i).id;
dataobj[temp_id]=results.rows.item(i).frist_name;
alert(dataobj[temp_id]);
}
else{
alert("No data present");
}
});
$(document).on("taphold",".namelist",function(event){
alert("I am in taphold event");
event.stopPropagation();
$(this).simpledialog2({
mode:"blank",
headerText:"Image Options",
showModal:false,
forceInput:true,
headerClose:true,
blankContent:"<ul data-role='listview'><li><a href=''>Edit</a></li><li><a href=''>Delete</a></li></ul>"
});
});
});
}
here is the js and css files in using:
<link rel="stylesheet" href="contactcss/jquery.mobile-1.3.1.min.css">
<link rel="stylesheet" href="css/jquery.mobile.simpledialog.min.css">
<script src="js/jquery.js"></script><script src="js/index.js"></script>
<script src="js/jquery.mobile-1.3.1.min.js"></script>
<script src="js/jquery.mobile.simpledialog2.min.js"></script>
<script type="text/javascript" charset="utf-8" src="js/cordova-2.7.0.js"></script>
here is the html code:
<div data-role="Content" >
<div data-role="listview" id="field">
<ul class="Name" id="name" data-role="listview" data-inset="true" data-theme="b">
</ul>
</div>
logcat Error i am getting:
07-13 17:29:33.145: D/CordovaLog(2696): TypeError: Result of expression 'o[0]' [undefined] is not an object.
07-13 17:29:33.145: E/Web Console(2696): TypeError: Result of expression 'o[0]' [undefined] is not an object. at file:///android_asset/www/js/jquery.mobile-1.3.1.min.js:4
Thanks in advance
When working with dynamically created content and jQuery Mobile you must use delegated event binding.
Instead of this:
$(".namelist").on("taphold",function(event){
bind it like this:
$(document).on("taphold",".namelist",function(event){
This solution don't care if .namelist exist or not. Tap event will be bound to document object and it will propagate to .namelist only when it become active in the DOM.

Custom Element - null reference from query() in constructor

I'm working on my first Dart app, having completed the Game of Darts tutorials. I am trying to create a semantically named top-menu element that will eventually display a list of navigation menu tabs at the top of my page. My Dart app is able to recognize my custom element and calls the associated constructor.
However, I am getting a null reference when trying to query for the UL element within my custom element. I need the UL reference in order to dynamically load my LI elements into the menu.
Question 1:
Should the element be visible in the DOM at the point where the constructor is running?
Question 2:
If it is not yet visible, is there a Dart event I can use to trigger loading of the LI elements after the custom element has been completely loaded into the DOM?
Thanks in advance! For reference, here is the source of my custom element:
topmenu-element.html
<!DOCTYPE html>
<html>
<body>
<element name="top-menu" constructor="TopMenu" extends="div">
<template>
<div>
Top Menu
<ul id="top-menu-list"></ul>
</div>
</template>
<script type="application/dart" src="topmenu-element.dart"></script>
</element>
</body>
</html>
topmenu-element.dart
import 'package:web_ui/web_ui.dart';
import 'dart:html';
class TopMenu extends WebComponent {
List menuItems = ['Session', 'Authentication Services', 'Vehicle Services', 'Subscriber Services', 'Data Services'];
void populateMenu() {
UListElement menuList = query('#top-menu-list');
LIElement newMenuItem = new LIElement();
newMenuItem.text = menuItems[0];
menuList.children.add(newMenuItem);
}
TopMenu() {
// populateMenu();
}
}
I can't speak specifically about the DOM visibility in a constructor with the query method as I'm truthfully not certain. However there are perhaps better methods which you can use, which are called at various stages in the elements lifecycle.
That said, can I ask why you need to use this particular method to add the children. It is probably much easier to do it with the template repeat like so:
<!DOCTYPE html>
<html>
<body>
<element name="top-menu" constructor="TopMenu" extends="div">
<template>
<div>
Top Menu
<ul id="top-menu-list">
<li template repeat="item in menuItems">{{item}}</li>
</ul>
</div>
</template>
<script type="application/dart" src="topmenu-element.dart"></script>
</element>
</body>
</html>
Then there's no need to put any of your menu display code in your constructor.

How do I structure a "Controller" in Dart's web_ui?

I have the following code
xviewcontainer.html
<!DOCTYPE html>
<html>
<head>
<title>xviewcontainer</title>
<link rel="components" href="xsearch.html">
<link rel="components" href="xcard.html">
</head>
<body>
<element name="x-view-container" constructor="ViewContainerComponent" extends="div">
<template>
<template instantiate="if view == 'SEARCH_VIEW'">
<x-search></x-search>
</template>
<template instantiate="if view == 'CARD_VIEW'">
<x-card></x-card>
</template>
</template>
</element>
<script type="application/dart" src="xviewcontainer.dart"></script>
<!-- for this next line to work, your pubspec.yaml file must have a dependency on 'browser' -->
<script src="packages/browser/dart.js"></script>
</body>
</html>
xviewcontainer.dart
import 'package:web_ui/web_ui.dart';
class ViewContainerComponent extends WebComponent {
String view = 'SEARCH_VIEW';
}
I have the event handling code within some other currently rendered sub-component of x-search. How do I get a reference to the containing x-view-container instance? I wish to change the .view property so that x-view-container will render x-card instead of the currently rendered x-search. I would be specifically interested in how to do so from my event handlers relative position, how to do it in a absolute fashion, as well as how to do so in any other manner.
void openCardView(){
WHAT_DO_I_PUT_HERE.view = 'CARD_VIEW';
}
You can query for the element you have on the DOM with query() method. Simplest example is query('x-view-container'). Or assign a class or an id on it and query against that. Then access the xtag property to get the actual web component instance.
Here's an example:
import 'package:web_ui/watcher.dart' as watchers;
main() {
// I'm assuming that the HTML tag is somewhere on the page.
query('x-view-container').xtag.view = 'CARD_VIEW';
watchers.dispatch(); // You may need to call this, or use #observable stuff.
}

Resources