I am trying to toggle (hide/unhide> a state dropdown menu when the USA is selected in a country dropdown menu
.html
<paper-dropdown-menu
label = "Country *"
selected-item-label = "{{countrySelectedItemLabel}}"
error-message = "Country is required"
id = "countryDdm">
<paper-menu class = "dropdown-content">
<template
is = "dom-repeat"
items = "[[countries]]"
as = "country">
<div>[[country.name]]</div>
<br>
</template>
</paper-menu>
</paper-dropdown-menu>
<div class = "layout horizontal">
<paper-dropdown-menu
hidden = $"[[hideState]]"
label = "State *"
selected-item-label = "{{stateSelectedItemLabel}}"
id = "stateDdm">
<paper-menu class = "dropdown-content">
<template
is = "dom-repeat"
items = "[[states]]"
as = "state">
<div>[[state.name]]</div>
<br>
</template>
</paper-menu>
</paper-dropdown-menu>
The relevant .dart code is shown below
##.dart
#property
bool hideState;
#property
String countrySelectedItemLabel = '';
#Listen( 'countryDdm.tap' )
void toggleStateOnUSASelection( event, [_] ) {
switch ( countrySelectedItemLabel ) {
case 'United States of America':
switch ( hideState ) {
case true:
hideState = false;
break;
case false:
break;
}
break;
}
}
void ready( ) {
set('hideState', true);
}
The application is displayed normally but when I select 'United States of America' the state combo is NOT shown. I would also like to hide the state combo if any country than the USA is selected.
Any help is appreciated. Thanks.
The $ is on the wrong position
hidden$="[[hideState]]"
The actual hidden attribute is set by Polymer. This is to work around issues with attributes like href of the <img> element where binding expressions (strings that aren't an actual URI to an image) would produce an error message before Polymer even had a chance to resolve the binding expression.
There are a few further issues (see the comments in the code)
dart
#HtmlImport('app_element.html')
library so33931432_hide_paper_dropdown.web.app_element;
import 'package:web_components/web_components.dart' show HtmlImport;
import 'package:polymer/polymer.dart';
import 'package:polymer_elements/paper_dropdown_menu.dart';
import 'package:polymer_elements/paper_menu.dart';
/// [PaperDropdownMenu], [PaperMenu]
#PolymerRegister('app-element')
class AppElement extends PolymerElement {
AppElement.created() : super.created();
#property
List<String> countries = ['Austria', 'Belgium', 'Czech Republic', 'United States of America'];
#property
bool hideState; // = true; // you could set a default value, then you don't need ready
// This way usually works better for me than #Listen
#Property(observer: 'toggleStateOnUSASelection')
String countrySelectedItemLabel = '';
// If `#Property(observer: ...) is used the function signature
// has to be changed
#reflectable
void toggleStateOnUSASelection(String label, [_]) {
switch (countrySelectedItemLabel) {
// I wasn't sure what you actually tried to accomplish here
// but this worked for me to reproduce your problem
case 'United States of America':
set('hideState', false);
break;
default:
set('hideState', true);
}
}
void ready() {
set('hideState', true);
}
}
html
<!DOCTYPE html>
<dom-module id='app-element'>
<template>
<paper-dropdown-menu
label="Country *"
selected-item-label="{{countrySelectedItemLabel}}"
error-message="Country is required"
id="countryDdm">
<paper-menu class="dropdown-content">
<template
is="dom-repeat"
items="[[countries]]"
as="country">
<div label="[[country]]">[[country]]</div>
</template>
</paper-menu>
</paper-dropdown-menu>
<div>selectedItem:<span>[[countrySelectedItemLabel]]</span> value: <span>[[countrySelectedItemLabel]]</span></div>
<div>hideState: <span>[[hideState]]</span></div>
<div class="layout horizontal">
<paper-dropdown-menu
hidden$="[[hideState]]"
label="State *"
selected-item-label="{{stateSelectedItemLabel}}"
id="stateDdm">
<paper-menu class="dropdown-content">
<template
is="dom-repeat"
items="[[states]]"
as="state">
<div>[[state.name]]</div>
<br>
</template>
</paper-menu>
</paper-dropdown-menu>
</div> <!-- missing in your question -->
</template>
</dom-module>
Related
I have the following snippets of a paper-dropdown-menu
.dart
....
#property
List<String> suffixes = <String>[
'I',
'II',
'III',
'Junior',
'Senior'
];
.html
<paper-dropdown-menu label = "Suffix">
<paper-menu class = "dropdown-content">
<template is = "dom-repeat"
items = "[[suffixes]]"
as = "suffix">
<paper-item>[[suffix]]</paper-item>
</template>
</paper-menu>
</paper-dropdown-menu>
What is the correct .dart code to get the selection made in the dropdown?
Thanks
There are several ways to achieve this.
The example below shows two ways using selected-item and selected-item-label
.html
<!DOCTYPE html>
<dom-module id='app-element'>
<template>
<paper-dropdown-menu label = "Suffix"
selected-item="{{selectedItem}}">
<paper-menu class = "dropdown-content">
<template id="ddmtr" is="dom-repeat"
items="[[suffixes]]"
as="suffix">
<paper-item label="suffix">[[suffix]]</paper-item>
</template>
</paper-menu>
</paper-dropdown-menu>
<div>selectedItem:<span>[[selectedItem]]</span> value: <span>[[selectedItemValue]]</span></div>
<paper-dropdown-menu label = "Suffix"
selected-item-label="{{selectedItemLabel}}">
<paper-menu class = "dropdown-content">
<template is="dom-repeat"
items="[[suffixes]]"
as="suffix">
<paper-item>[[suffix]]</paper-item>
<!-- <paper-item label="suffix">[[suffix]]</paper-item> -->
<!-- if the label attribute is not set, the text content is used -->
</template>
</paper-menu>
</paper-dropdown-menu>
<div>selectedItemLabel:<span>[[selectedItemLabel]]</span></div>
</template>
</dom-module>
.dart
#HtmlImport('app_element.html')
library so33770938_paper_dropdown_menu_selected.web.app_element;
import 'dart:html' as dom;
import 'package:web_components/web_components.dart' show HtmlImport;
import 'package:polymer/polymer.dart';
import 'package:polymer_elements/paper_dropdown_menu.dart';
import 'package:polymer_elements/paper_menu.dart';
import 'package:polymer_elements/paper_item.dart';
/// [PaperDropdownMenu], [PaperMenu], [PaperItem]
#PolymerRegister('app-element')
class AppElement extends PolymerElement {
AppElement.created() : super.created();
#property var selectedItem;
#property var selectedItemLabel;
#Property(computed: 'getSelectedItemValue(selectedItem)')
String selectedItemValue;
#reflectable
String getSelectedItemValue(dom.Element selectedItem) {
DomRepeatModel model =
($['ddmtr'] as DomRepeat).modelForElement(selectedItem);
return suffixes[model.index];
}
#property
List<String> suffixes = <String>[
'I',
'II',
'III',
'Junior',
'Senior'
];
}
EDITED: NOW WITH COMPLETE CODE
Previous Post related
LinkPaths works, but does not fire all on-change event of the elements where the data changed. See the image:
For example, when data is changed on <paper-input label="Produto" value="{{item.descricao}}"></paper-input> (outer dom-repeat) the data in element <paper-input label="Produto Componente" value="{{item_comp.descricao}}" on-change="mudou"></paper-input> (inner dom-repeat) change too. It´s works nice because of the linkPaths!
But on-change="mudou" does not fire.
Just fire if data entry directly on <paper-input label="Produto Componente" value="{{item_comp.descricao}}" on-change="mudou"></paper-input> (inner dom-repeat)
main_app.html
<dom-module id="main-app">
<style>
:host {
display: block;
}
</style>
<template>
<h3>Lista de Produtos</h3>
<template is="dom-repeat" items="{{produtos}}" as="item">
<div class="layout vertical">
<paper-material elevation="1">
<div class="layout horizontal">
<paper-input label="Produto" value="{{item.descricao}}"></paper-input>
</div>
</paper-material>
<template is="dom-repeat" items="{{item.componentes}}" as="item_comp">
<div class="layout vertical">
<div class="layout horizontal">
<paper-input label="Produto Componente" value="{{item_comp.descricao}}" on-change="mudou"></paper-input>
</div>
</div>
</template>
</div>
</template>
</template>
</dom-module>
main_app.dart
import 'dart:html';
import 'package:polymer_elements/paper_input.dart';
import 'package:polymer_elements/paper_fab.dart';
import 'package:polymer_elements/iron_icons.dart';
import 'package:polymer_elements/paper_material.dart';
import 'package:polymer/polymer.dart';
import 'package:web_components/web_components.dart';
#PolymerRegister('main-app')
class MainApp extends PolymerElement {
#Property(notify: true)
List<Produto> produtos = new List();
MainApp.created() : super.created();
void ready() {
Produto p = new Produto()..descricao = 'componente 1';
add('produtos', p);
Produto p2 = new Produto()..descricao = 'componente 2';
add('produtos', p2);
Produto p3 = new Produto()..descricao = 'composto';
add('produtos', p3);
add('produtos.2.componentes', p);
add('produtos.2.componentes', p2);
linkPaths('produtos.2.componentes.0', 'produtos.#0');
linkPaths('produtos.2.componentes.1', 'produtos.#1');
linkPaths('produtos.0', 'produtos.#2.componentes.#0');
linkPaths('produtos.1', 'produtos.#2.componentes.#1');
}
#reflectable
void adicionarProduto(e, d) {
//...
}
#reflectable
mudou(e, d) {
window.alert('teste');
}
}
class Produto extends JsProxy {
#reflectable
String descricao;
#reflectable
List<Produto> componentes;
Produto() {
componentes = new List();
}
}
Is this normal in Polymer? How I can to force fire on-change?
I found a workaround solution.
I used computed binding method, no more on-change event. This form, I passed the paper-input value reference on method call, and all time that value change, the method is called.
The code changed:
.html
...
<paper-input label="Produto Componente" value="{{item_comp.descricao}}"></paper-input>
<span>{{mudou(item_comp.descricao)}}</span>
...
.dart
...
#reflectable
void mudou(a) {
window.alert('teste');
}
...
I'm trying to create a custom Polymer element that extends paper-shadow to display a Tweet.
Here is my implementation:
tweet_element.html
<link rel="import" href="packages/paper_elements/paper_shadow.html">
<link rel="import" href="packages/polymer/polymer.html">
<link rel="stylesheet" href="tweet_element.css">
<polymer-element name="tweet-element" extends="paper-shadow">
<template>
<div id="header">
<div id="user-image">
<img src="{{userImageUrl}}">
</div>
<div id="details">
<div id="user">{{user}}</div>
<div id="date-published">{{datePublished}}</div>
</div>
</div>
<div id="content">
<div id="text">{{text}}</div>
<div id="photos">{{photos}}</div>
</div>
</template>
<script type="application/dart" src="twitter.dart"></script>
</polymer-element>
twitter.dart
import 'package:polymer/polymer.dart';
#CustomTag('tweet-element')
class TweetElement extends PolymerElement {
#Observable String userImageUrl;
#Observable String user;
#Observable String datePublished;
#Observable String text;
TweetElement.created() : super.created();
void update(Tweet tweet) {
userImageUrl = tweet.user.profileImage;
user = '${tweet.user.name} (#${tweet.user.screenName})';
datePublished = _parseDate(tweet.date);
text = tweet.text;
}
...
}
And finally the code that creates a TweetElement and tries to add it to the DOM:
import 'dart:html';
import 'package:polymer/polymer.dart';
import 'twitter.dart';
...
var mainContent = querySelector('#main-content');
var element;
for (var tweet in tweets) {
element = new TweetElement.created();
element.update(tweet);
mainContent.children.add(element);
}
And when I run this I get:
Exception: Uncaught Error: created called outside of custom element creation.
So then I tried to change twitter.dart to:
TweetElement.created() : super.created();
TweetElement (Tweet tweet) {
TweetElement.created();
userImageUrl = tweet.user.profileImage;
user = '${tweet.user.name} (#${tweet.user.screenName})';
datePublished = _parseDate(tweet.date);
text = tweet.text;
}
And add the element to the DOM like this:
var mainContent = querySelector('#main-content');
var element;
for (var tweet in tweets) {
element = new TweetElement(tweet);
mainContent.children.add(element);
}
And now I got this error:
Internal error: unresolved implicit call to super constructor 'PolymerElement()' TweetElement (Tweet tweet) {
Ralph.
You can do that in two ways:
Option A
If you want to create a Polymer Element in your Dart code, you just have to create that tag this way:
var myTweetElement = new Element.tag ('tweet-element');
mainContent.childern.add(myTweetElement);
Also, check that you have imported the html library:
import 'dart:html';
Option B: (the coolest one)
You can do it extra convenient (and more object oriented) by adding this factory to your twitter.dart:
factory TweetElement () => new Element.tag('tweet-element');
Then, the creation of the tag in your dart code, is more readable:
var myTweetElement = new TweetElement (); // This uses the factory transparently
mainContent.children.add(myTweetElement);
Additionally, you can set the values of your properties. As those are observable, the bindings will update automagically:
myTweetElement.userImageUrl = "foo"
myTweetElement.user = "bar"
myTweetElement.datePublished = "baz"
myTweetElement.text = "qux"
Or if you like the cascade operator, you can write this instead:
myTweetElement..userImageUrl = "foo"
..user = "bar"
..datePublished = "baz"
..text = "qux";
Hope this helps.
I am trying to change an icon when a specific radio-button is selected.
However, the switch statement in the .dart code never changes the icon even though the switch is triggered.
Thanks for any help.
.dart
class Gender extends Object with Observable {
#observable
String sex = '';
}
#observable String ikon = 'alarm';
void onChangeRadioGroupHandler(dom.CustomEvent e) {
gender.sex = (e.target as PaperRadioButton).label;
switch(gender.sex)
{
case 'Male':
ikon = 'done';
break;
case 'Female':
ikon = 'cached';
break;
}
.html
<div layout vertical center>
<div layout horizontal self-center>
<paper-icon-button icon='{{ikon}}' on-click='{{toggle}}'></paper-icon-button>
</div>
</div>
<core-collapse id='core--collapse'>
<div layout vertical'>
<label id='genderLbl'></label>
<paper-radio-group id='gender-group' on-change='{{onChangeRadioGroupHandler}}'>
<paper-radio-button name='Male' label='Male'></paper-radio-button><br>
<paper-radio-button name='Female' label='Female'></paper-radio-button>
</paper-radio-group>
</div>
</core-collapse>
</div>
Unsupported operation: Can't use ownerName in reflection because it is not included in a #MirrorsUsed annotation.
ownerName is just an published attribute on the polymer element. I understand there are a few things out there (on web, not on here) like this but none have a solid answer...
I also get this below it:
NoSuchMethodError : method not found: 'Symbol("title")'
Anyone got any ideas. Been wrestling with this for 3 hours and ready to dump polymer. Though It was fun in dartium, if it cannot convert to JS I see no real use in it.
import 'package:polymer/polymer.dart';
import 'package:google_postendpoint_v1_api/postendpoint_v1_api_browser.dart';
import 'package:google_postendpoint_v1_api/postendpoint_v1_api_client.dart';
import 'dart:math';
//import 'package:intl/intl.dart';
/**
* A Polymer post element.
*/
#CustomTag('post-element')
class SoberSky extends PolymerElement {
#published int count = 0;
#published String ownerName = "Casey";
#published int ownerId = 888;
#published int postId = 333;
#published String content = "yo ho ho, and a bottle of rumsky!";
#published String postContent = "This is an example of post content";
#published int getOwnerId = 333;
#published CollectionResponse_Comment listComment;
#published CollectionResponse_Post listPost;
#published String listCommentHTML;
#published Post currentPost;
#published bool yes = false;
Postendpoint endpoint = new Postendpoint();
var rng = new Random();
var commentList;
SoberSky.created() : super.created() {
endpoint.rootUrl = "http://localhost:8888/"; // set the root URL
}
void getListComment([int tempPostId]) {
if (tempPostId == null) {
tempPostId = postId;
}
endpoint.listComment( tempPostId ).then((CollectionResponse_Comment commentCollection){
this.listComment = commentCollection;
}).catchError((e) => handleError(e));
}
void getPost() {
endpoint.getPost( postId ).then((Post loadedMessage) {
currentPost = loadedMessage;
getListComment(currentPost.key);
}).catchError((e) => handleError(e));
}
void submitComment() {
int id = rng.nextInt(1000);
Comment comment = new Comment.fromJson({});
comment.id = id;
comment.content = content;
comment.postId = postId;
comment.ownerName = ownerName;
comment.ownerId = ownerId;
endpoint.insertComment( comment ).then((Comment savedComment) => endpoint.getComment(id)).
then((Comment loadedMessage) {
print(loadedMessage.content);
getListComment(loadedMessage.postId);
}).catchError((e) => handleError(e));
}
void submitPost(){
postId = rng.nextInt(1000);
Post post = new Post.fromJson({});
post.key = postId;
post.ownerName = ownerName;
post.ownerId = ownerId;
post.title = postContent;
endpoint.insertPost( post ).then((Post savedPost) => endpoint.getPost(postId)).
then((Post loadedMessage) {
print(loadedMessage.title);
getPost();
getListComment(loadedMessage.key);
}).catchError((e) => handleError(e));
}
void handleError(Error e) {
print("We had an error: ");
print(e.toString());
}
#override
void attached() {
}
}
The HTML Polymer element
<polymer-element name="click-counter" attributes="count">
<template>
<form action="javascript:void(0);" >
<div class="entry">
<label>Enter Post:</label>
<input id="subject" type="text" value="{{postContent}}" size="45" maxlength="255">
<button on-click="{{submitPost}}" class="btn btn-success" >Submit Post</button> <br>
</div>
</form>
<div class="post">
<h3>{{ currentPost.ownerName }}</h3>
<p>{{ currentPost.title }}</p>
<p>This is the postId: {{ currentPost.key }}</p>
<p class="timestamp">{{ currentPost.uploadTime }}</p>
<template repeat="{{comment in listComment.items}}">
<div class="comment">
<h3>{{ comment.ownerName }}</h3>
<p>{{ comment.content }}</p>
<p>This is the commentId: {{ comment.id }}</p>
<p class="timestamp">{{ comment.formatDate }}</p>
</div>
</template>
<form action="javascript:void(0);">
<label>Enter Comment:</label>
<input id="subject" type="text" value="{{content}}" size="45" maxlength="255">
<button on-click="{{submitComment}}" class="btn btn-success">Submit Comment</button> <br>
</form>
</div>
</template>
<script type="application/dart" src="clickcounter.dart"></script>
</polymer-element>
I have not yet seen your Unsupported operation message. Maybe some recent change. Your NoSuchMethodError is common when a property of a class is only referenced by a polymer expression (HTML) because tree-shaking drops all code that is not referenced and polymer expressions are not evaluated for this yet. The #MirrorsUsed annotation helps bridging this gap.
The problem is in your Post class because it's properties are only referenced in polymer expressions
<div class="post">
<h3>{{ currentPost.ownerName }}</h3>
<p>{{ currentPost.title }}</p>
<p>This is the postId: {{ currentPost.key }}</p>
<p class="timestamp">{{ currentPost.uploadTime }}</p>
To get your view updated when the properties in your currentPost change you should make your Post class like
class Post extends Object with Observable {
#observable String ownerName;
#observable String title;
...
}
If you have an annotation like #reflectable, #published, or #observable you don't need #MirrorsUsed.