Numeric for loop in Dart Polymer templates - dart

How do I write a numeric for loop in a polymer custom element template? I mean something like
<template repeat="{{for i = 1 to 10}}">
<div>item</td>
</template>
Is it possible in the current version of Dart 1.0?

Currently no, this is not possible in Polymer.dart (or Polymer.js to my knowledge). The repeat binding requires an iterable (See Repeating Templates section of the Polymer_expressions library). Unfortunately due to Issue 12669 it is also not possible to use a list literal to accomplish this either.
Using a filter we can accomplish this:
<!-- myelement.html -->
<polymer-element name="my-element">
<template>
<div>
<template repeat="{{ 5 | myFilter }}">
<p>Write me {{ }}</p>
</template>
</div>
</template>
<script type="application/dart" src="myelement.dart"></script>
</polymer-element>
// myelement.dart
import 'package:polymer/polymer.dart';
import 'package:polymer_expressions/filter.dart';
#CustomTag('my-element')
class MyElement extends PolymerElement {
final Transformer myFilter = new GenerateIterable();
MyElement.created() : super.created();
}
class GenerateIterable extends Transformer<Iterable, int> {
int reverse(Iterable i) => i.length;
Iterable forward(int i) => new Iterable.generate(i, (j) => j + 1);
}
Creating a page which imports myelement.html and using <my-element></my-element> will output:
<div>
<p>Write me 1</p>
<p>Write me 2</p>
<p>Write me 3</p>
<p>Write me 4</p>
<p>Write me 5</p>
</div>

Related

Template data binding

I'm trying to create a custom element with data binding.
Here is my custom element template:
<link rel="import" href="packages/paper_elements/paper_shadow.html">
<link rel="import" href="packages/polymer/polymer.html">
<polymer-element name="tweet-element">
<template>
<link rel="stylesheet" href="tweet_element.css">
<paper-shadow z="1">
<div id="header" horizontal layout>
<div id="user-image">
<img _src="{{profileImage}}">
</div>
<div id="user-details" flex>
<div horizontal layout>
<div id="name">{{name}}</div>
<div id="screen-name">(#{{screenName}})</div>
</div>
<div id="date-published">{{date}}</div>
</div>
</div>
<div id="content">
<div id="text">{{text}}</div>
</div>
</paper-shadow>
</template>
<script type="application/dart" src="twitter.dart"></script>
</polymer-element>
twitter.dart
import 'dart:html';
import 'package:polymer/polymer.dart';
import 'package:polymer_expressions/polymer_expressions.dart';
#CustomTag('tweet-element')
class TweetElement extends PolymerElement {
#Observable String profileImage;
#Observable String name;
#Observable String screenName;
#Observable String date;
#Observable String text;
TweetElement.created() : super.created();
factory TweetElement() => new Element.tag('tweet-element');
}
This is how I'm creating and adding the elements:
main.dart
import 'dart:html';
import 'package:polymer/polymer.dart';
import 'package:polymer_expressions/polymer_expressions.dart';
import 'twitter.dart';
void main() {
...
var mainContent = querySelector('#main-content');
var element;
for (var tweet in tweets) {
element = new TweetElement();
element
..profileImage = tweet.user.profileImage
..name = tweet.user.name
..screenName = tweet.user.screenName
..date = _parseDate(tweet.date)
..text = tweet.text;
mainContent.children.add(element);
}
}
The tweet-element elements and being added to the DOM, but the fields with data binding are blank:
There is no problem with the tweet objects, because I've tried setting the element fields with other Strings and it also didn't work.
If you have a custom main method in a Polymer.dart application, you need to take care of Polymer initialization yourself.
See how to implement a main function in polymer apps for more details.
I managed to solve the problem. I was using the #Observable tag instead of #observable (notice upper/lowercase letters).

How to update the view on property change of objects in ObservableMap?

I have an observable map, which maps arbitrary objects (say another maps) to their id's. When I make changes to these objects, the objects should be updated in the view, too. However, I didn't get it to work. Here is my setup so far:
myexample.html
<polymer-element name="my-example">
<script type="application/dart" src="myexample.dart"></script>
<template>
<style></style>
<div>
<ul>
<template repeat="{{ entry in map.values }}">
<li>{{ entry }}</li>
</template>
</ul>
<button on-click="{{change}}">Change</button>
</div>
</template>
</polymer-element>
myexample.dart
#CustomTag('my-example')
class MyExample extends PolymerElement {
#observable Map<int, String> map = toObservable({'123': {'name': 'XYZ', 'size': 12}});
MyExample.created() : super.created() {
map.changes.listen((_) => notifyPropertyChange(#map, 1, 0));
}
void change() {
var object = map['123']
object['size'] = 100;
map.notifyChange(new MapChangeRecord('123', null, object));
}
}
On clicking the 'Change'-Button, the object with id '123' is updated in the map, but isn't updated in view. Has anyone an idea, how to deliver the changes to the view?
<link rel="import" href="../../packages/polymer/polymer.html">
<polymer-element name="app-element">
<template>
<div>
<ul>
<template repeat="{{ entry in map.values }}">
<li>x{{ entry['name'] }} {{ entry['size']}}</li>
<template repeat="{{ item in entry.values}}">
y{{item}}
</template>
</template>
</ul>
<button on-click="{{change}}">Change</button>
</div>
</template>
<script type="application/dart" src="app_element.dart"></script>
</polymer-element>
import 'package:polymer/polymer.dart';
#CustomTag('app-element')
class AppElement extends PolymerElement {
#observable
Map map = toObservable({'123': {'name': 'XYZ', 'size': 12}});
AppElement.created() : super.created();
void change() {
var object = map['123']['size'] = 100;
}
}

Bind JSON key value pairs to table template in polymer dart

how I can bind to the key/value pairs within a json object in polymer notation. i have template repeat="{{objects in jsonarray}}"... I want to lay out a table. say each object has {1: one, 2: two, 3: three}
something like:
<template repeat="{{item in mylist}}">
<tr>
<template repeat="{{key, value in item}}">
<td>{{key}}: {{value}}</td>
</template>
</tr>
</template>
this code works for me:
Dart:
#observable List jsonlist = toObservable(JSON.decode('[{"1":"one"},{"2":"two"}]'));
HTML:
<template repeat="{{ foo in jsonlist }}">
{{ foo }}
<template repeat="{{ key in foo.keys }}">
{{ key }} = {{ foo[key] }}
</template>
</template>
With this code I get the following output:
{1: one} 1 = one {2: two} 2 = two
Regards
Robert
I think it should work this way:
<template repeat="{{item in mylist}}">
<tr>
<template repeat="{{key in item.keys}}">
<td>{{key}}: {{item[key]}}</td>
</template>
</tr>
</template>
Please try and add a comment when it doesn't work (so I get a notification) then I build a demo app and try it myself.
I managed to get this working the way I wanted, which was to output a JSON array of JSON objects to a table, like this:
jsontable.dart
import 'package:polymer/polymer.dart';
import 'dart:html';
import 'dart:convert';
#CustomTag('json-table')
class jsontable extends PolymerElement {
#observable List jsonarray = [{"id":1,"description":"cat"},{"id":2,"description":"dog"}, {"id":3,"description":"fairy"}];
jsontable.created() : super.created() {}
}
jsontable.html
<polymer-element name="json-table">
<template>
<div>
<table border="1">
<tbody>
<thead>
<tr>
<template repeat="{{ key in jsonarray.first.keys }}">
<th>{{key}}</th>
</template>
</tr>
</thead>
<template repeat="{{ jsonobject in jsonarray }}">
<tr>
<template repeat="{{ value in jsonobject.values }}">
<td>{{value}}</td>
</template>
</tr>
</template>
</tbody>
</table>
</div>
</template>
<script type="application/dart;component=1" src="jsontable.dart"></script>
</polymer-element>

Nested Polymer Element Not Attached When Run As JavaScript

I have built a Polymer.dart app that uses nested Polymer elements. The parent element takes an attribute and passes its value to the nested, child elment as an attribute. This works fine when "Run in Dartium" from within DartEditor, but the nested element fails to load after the app is "Pub Built" and "Run as JavaScript." There are no error messages during the build process, or any pointers of any other sort. I don't know how to debug this and the fact that it runs as expected without any warnings or errors in Dartium doesn't help.
The following is the code for the simplified version of my app that produces the same problem. my_view is the parent element and my_form is the nested element that is attached when my_view is loaded.
main.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sample</title>
<link rel="import" href="my_view.html">
<script type="application/dart">export 'package:polymer/init.dart';</script>
<script src="packages/browser/dart.js"></script>
</head>
<body>
<h1>The view polymer element should appear below:</h1>
<my-view viewAttribute="My_Value"></my-view>
</body>
</html>
my_view.html
<polymer-element name="my-view" attributes="viewAttribute">
<link rel="import" href="my_form.html">
<template>
<div style="width: 100%;"><h1>The form should appear below:</h1></div>
<div id="form_div" style="width: 100%;"></div>
</template>
<script type="application/dart" src="my_view.dart"></script>
</polymer-element>
my_view.dart
import 'package:polymer/polymer.dart';
import 'dart:html';
#CustomTag('my-view')
class MyView extends PolymerElement {
#published String viewAttribute;
DivElement _formSlot;
MyView.created() : super.created() {
_formSlot = $['form_div'];
}
void viewAttributeChanged() {
_formSlot..append(new Element.tag('form', 'my-form')..setAttribute("formAttribute", viewAttribute));
}
}
my_form.html
<polymer-element name="my-form" extends="form" attributes="formAttribute">
<template>
<div style="width: 100%;">Attribute value: {{formAttribute}}</div>
<div style="width: 100%;">
<label for="nameInput">name:</label>
<input id="nameInput" type="text" value="{{nameValue}}" />
</div>
<div style="width: 100%;">
<div id="button_div">
<input type="submit" on-click="{{submitForm}}" value="send" />
</div>
</div>
</template>
<script type="application/dart" src="my_form.dart"></script>
</polymer-element>
my_form.dart
import 'package:polymer/polymer.dart';
import 'dart:async';
import 'dart:html';
import 'dart:convert';
#CustomTag('my-form')
class MyForm extends FormElement with Polymer, Observable {
#published String formAttribute;
#observable String nameValue;
HttpRequest _request;
MyForm.created() : super.created();
void submitForm(Event e, var detail, Node target) {
e.preventDefault();
_request = new HttpRequest();
_request.onReadyStateChange.listen(_onData);
_request.open('POST', 'http://my.server.com/contact_form');
_request.send(JSON.encode({'name': nameValue, 'attribute': formAttribute}));
}
_onData(_) {
if (_request.readyState == HttpRequest.DONE) {
switch (_request.status) {
case 200:
// Data was posted successfully
break;
case 0:
// Post failed
break;
}
}
}
}
Any help, hints, well wishes, prayers would be greatly appreciated! Thanks!
I guess this is a dart2js bug.
For answering this question Dynamically create polymer element I built an example.
This code (like you showed in your question) generates the correct markup but the form element didn't work properly. I didn't examine this behaviour further because I myself never needed to extend a DOM element.
You could also try not to extend the <FORM> element but create a new Polymer element and just embed the <FORM> element.

Polymer Elements trigger update

If I have two completely different polymer elements, and in one i have
<template if="{{MyVar}}">htmlhere</template>
<template if="{{!MyVar}}">otherhtmlhere</template>
the other i have
<template if="{{MyVar}}">hello</template>
<template if="{{!MyVar}}">world</template>
what I want to do is if on one MyVar changes, it should change on the other as well... How would I handle this situation?
To explain further what I am looking for is in effect a way to have various bindings / reactions throughout the whole page... so if some method / module somewhere changes MyVar's state it would ripple through the entire page make changes where it should
I have a similar situation where I have an observable object in the root polymer element which I assign to an attribute of the child polymer element.
The child polymer element can then bind to this attribute.
AppModel (global model)
class AppModel extends Object with Observable {
#observable bool isLoggedIn = false;
#observable List<String> authenticationProvider = ['Google', 'Yahoo', 'GitHub', 'Amazon'];
}
#CustomTag("app-element")
class AppElement extends PolymerElement {
#observable AppModel appModel;
AppElement.created() : super.created() {
}
}
AppElement (html) here the global model get's assigned to a child element
<polymer-element name="app-element">
<template>
<my-login id="mylogin" model="{{appModel}}"></my-login>
</template>
...
</polymer-element>
MyLogin (dart) the model Attribute is assigned to the model field.
#CustomTag("my-login")
class MyLogin extends PolymerElement {
MyLogin.created() : super.created();
#published AppModel model;
}
MyLogin (html) the global model is used to show/hide the login button/logged-in user info
<polymer-element name="bwu-login">
<template>
<template if="{{!model.isLoggedIn}}">
<bs-dropdown>
<div class="dropdown">
<div class="dropdown-toggle btn btn-default btn-xs navbar-btn" role="button" data-toggle="dropdown">
<span class="glyphicon glyphicon-log-in"></span> Login
</div>
<ul class="dropdown-menu" role="menu" aria-labelledby="select authentication provider">
<template repeat="{{ap in model.authenticationProvider}}">
<li role="presentation">
<a role="menuitem" tabindex="-1" href="{{ap.authenticationUrl}}" on-click="{{openLogin}}" target="_blank">{{ap.name}}</a>
</li>
</template>
</ul>
</div>
</bs-dropdown>
</template>
<template if="{{model.isLoggedIn}}">
<small>{{model.name}}<template if="{{model.isAdmin}}"> (Admin)</template></small>
<div id="logoutButton" on-click="{{onLogoutHandler}}" class="btn btn-default btn-xs navbar-btn" role="button">
<span class="glyphicon glyphicon-log-out"></span> Logout
</div>
<!--<div><img src="{{model.avatar}}"></img>{{model.name}} <button id="logout">Log out</button></div>-->
</template>
</template>
<script type="application/dart" src='my_login.dart'></script>
</polymer-element>

Resources