I want to check if the user is logged in on element creation and eventually redirect him if the user is not. The problem is that the domHost.signedIn property is false even though the user is signedIn. If I check the property later(for example when I call a function with button tap) the property is true as it should be.
Here is the code:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="/bower_components/paper-button/paper-button.html">
<dom-module id="settings-view">
<template>
<style>
</style>
TODO: user settings
<paper-button on-tap="debugFunction">button</paper-button>
</template>
<script>
Polymer({
is: 'settings-view',
ready: function () {
console.log(this.domHost.signedIn); // false
console.log(this.domHost.user); // null
},
debugFunction: function () {
console.log(this.domHost.signedIn); // true
console.log(this.domHost.user); // user object
}
});
</script>
</dom-module>
What is the best way to check if the user is signedIn in child element? Would setting the signedIn value to iron-meta element be a better approach?
Thanks, Jan
You're better off declaring properties with observers on them. Observers will execute the function as soon as the property's value is something other than undefined. So your code will look like this:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="/bower_components/paper-button/paper-button.html">
<dom-module id="settings-view">
<template>
<style>
</style>
TODO: user settings
</template>
<script>
Polymer({
is: 'settings-view',
properties: {
signedIn: {
type: Boolean,
observer: '_signedInChanged'
},
user: {
type: Object,
observer: '_userChanged'
},
},
_signedInChanged: function (newSignedInValue) {
console.log(newSignedInValue); // true
console.log(this.signedIn); // true
},
_userChanged: function (newUserValue) {
console.log(newUserValue); // user object
console.log(this.user); // user object
}
});
</script>
</dom-module>
Then when you update those signedIn and user values through JavaScript or data binding, the observers will call the associated functions.
Related
The thing is that this object name changes from an array list, and i dont really understand how could i bind them. I want to extract the id from the response and profileIconId. It would be simple for one user, but i have a lot of them. Thank you in advance for the help!
This is my code:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="shared-styles.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="my-summoner">
<template>
<style>
:host {
display: block;
}
</style>
<iron-ajax
auto
url="[[_summonerName(name)]]"
handle-as="json"
last-response="{{names}}"></iron-ajax>
<h1>[[name]]</h1>
<span>{{names.~dynamic user name~.name}}</span>
</template>
<script>
Polymer({
is: 'my-summoner',
properties: {
name: {
type: String,
value: '',
notify: true
},
},
_summonerName: function(name){
return 'https://api.leagueofzabalt.club/summoner/by-name/' + name;
}
});
</script>
</dom-module>
This is the response:
{"lordfumeitor": {
"id": 19347567,
"name": "lord fumeitor",
"profileIconId": 1385,
"revisionDate": 1479073568000,
"summonerLevel": 30
}}
It seems that iron-ajax doesn't know how to handle objects as responses. The one work-around is to use the results value in the api return and force it into a dom repeat template, since it corresponds with an array, albeit of a single object. The response would look something like this:
results: [
{
"lordfumeitor": {
"id": 19347567,
"name": "lord fumeitor",
"profileIconId": 1385,
"revisionDate": 1479073568000,
"summonerLevel": 30
}
}
]
Assuming you're grabbing name from the element like so:
<my-summoner name="lordfumeitor"></my-summoner>
You would then be able to grab the returned data and output it to a template:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="shared-styles.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="my-summoner">
<template>
<style>
:host {
display: block;
}
</style>
<iron-ajax
auto
url="[[_summonerName(name)]]"
handle-as="json"
on-response="responseHandler">
</iron-ajax>
<template is="dom-repeat" items=[[data]]>
<h1>[[data.name]]</h1>
<span>[[data.name.id]]</span>
<span>[[data.name.profileIconId]]</span>
</template>
</template>
<script>
Polymer({
is: 'my-summoner',
properties: {
name: String,
},
created: function() {
name = this.getAttribute('name');
},
_summonerName: function(name){
return 'https://api.leagueofzabalt.club/summoner/by-name/' + name;
},
responseHandler: function(request) {
data = JSON.parse(request.detail.response);
return this.data = data.results;
}
});
</script>
</dom-module>
I'm adding some items to an Array, using the Array mutation methods. The items are displayed within a <dom-repeat> and can can be edited on the fly. While the edits do change the data in the object, any attached observers do not fire to indicate that a change occurred.
tl;dr
I'm properly using the Array mutation methods to push items
this.push("data.contents", {
id: 1,
name: "Modifying this text doesn't trigger an observer"
});
I'm displaying the items in a dom-repeat
These items are displayed using a <dom-repeat>, and the sub-property name is displayed in a <paper-input> where they can be amended on the fly.
<template>
<template is="dom-repeat" items="[[data.contents]]">
<paper-input value="{{item.name::input}}"></paper-input>
</template>
</template>
It seems that while the data is modified in the object itself, any attached observers do not fire for these sub-properties.
I'm attaching wildcard observers
I'm observing using the usual wildcard observers like so:
observers: [
"logChange(data.*)"
],
Notes
Note that:
Changing the item via a direct this.set() like so:
this.set("data.contents.0.name", "Foo")
will trigger the observers just fine
An MCVE for the above.
How to use:
Press the button to push some items to the Array
Edit any one of the added items
Console should log that a change occurred in any of the items (it doesn't)
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-input/paper-input.html" rel="import">
<link href="paper-button/paper-button.html" rel="import">
<dom-module id="x-example">
<template>
<paper-button on-tap="pushItem">Push to Array</paper-button>
<template is="dom-repeat" items="[[data.contents]]">
<paper-input value="{{item.name::input}}"></paper-input>
</template>
</template>
<script>
HTMLImports.whenReady(function() {
"use strict";
Polymer({
is: "x-example",
properties: {
data: {
type: Object,
value: {
contents: []
}
}
},
observers: [
"logChange(data.*)"
],
pushItem: function() {
this.push("data.contents", {
id: 1,
name: "Modifying this text doesn't trigger an observer"
})
},
logChange: function() {
console.log("change occured!");
}
});
});
</script>
</dom-module>
<x-example></x-example>
Solved here: https://github.com/Polymer/polymer/issues/4140#issuecomment-259465035
The observer isn't firing because you have one-way binding annotations on the items property, which prevents change notifications from flowing up to the element. Change it to: items="{{data.contents}}" and you'll see the changes.
In essence, turn this:
<template is="dom-repeat" items="[[data.contents]]">
<paper-input value="{{item.name::input}}"></paper-input>
</template>
to this
<template is="dom-repeat" items="{{data.contents}}">
<paper-input value="{{item.name::input}}"></paper-input>
</template>
Whats the difference between defining a computed property and using it like {{prop}}
prop: {
type: String,
computed: 'some(prop1)'
}
vs a function binding like
{{some(prop1)}}
The property is, as the name implies, also a property of the node object. It can notify outside listeners or reflect to attribute.
Function binding is only used to that. You can call it from the outside but it should have no effect - assuming that the function has no side-effects which is shouldn't.
The most important difference however, is that compute function will evaluate for each binding usage. Computed property will evaluate only once when a dependency changes. See below what happens in the console whenever you click INCREMENT.
Polymer({
is: 'my-elem',
properties: {
i: {
type: Number,
value: 0
},
c: {
computed: 'compute(i)'
}
},
inc: function() {
console.clear();
this.i += 1;
},
compute: function(i) {
console.log('computing property binding');
return i * 2;
},
f: function(i) {
console.log('computing function binding');
return i * 2;
}
});
<!DOCTYPE html>
<html>
<head>
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import"/>
<link href="paper-button/paper-button.html" rel="import" />
</head>
<body>
<my-elem></my-elem>
<dom-module id="my-elem">
<template>
<div>Computed: [[c]]</div>
<div>Computed: [[c]]</div>
<div>Computed: [[c]]</div>
<div>Computed: [[c]]</div>
<div>Function: [[f(i)]]</div>
<div>Function: [[f(i)]]</div>
<div>Function: [[f(i)]]</div>
<div>Function: [[f(i)]]</div>
<paper-button on-tap="inc">Increment</paper-button>
</template>
</dom-module>
</body>
</html>
I have switch.html like this:
<link rel="import" href="/public/components/paper-toggle-button/paper-toggle-button.html">
<dom-module id="element-name">
<template>
<div><paper-toggle-button on-change="{{handleToggle}}"></paper-toggle-button></div>
</template>
<script>
// element registration
Polymer({
is: "element-name",
properties: {
greeting: {
type: String,
value: "Hello!"
}
},
handleToggle: function() {
alert('Ow!')
}
});
</script>
</dom-module>
version: 1.2.0
How do I catch change event and handle it? I have set on-change property, but it does not work. Next, I need to send json to my server.
You have wrapped handleToggle in curly braces which makes it a binding. Just remove them to tell on-change to call a function:
<paper-toggle-button on-change="handleToggle"></paper-toggle-button>
Did you try this:
on-change="handleToggle"
handleToggle is not a property, so you do not have to use {{}}.
I'm working on a reddit client using polymer to check out web compoments technologies. I started with the 0.5 version and got back on this project recently. That when I found out that polymer had the 1.0 released so I started over (as it wasn't that advanced anyway).
I have a service that use the iron-ajax to request reddit api and look for the posts. Here is the code :
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="reddit-list-service">
<template>
<iron-ajax
url='https://www.reddit.com/new.json'
handle-as='json'
debounce-duration="300"
on-response='handleResponse'
debounce-duration="300"
auto>
</iron-ajax>
</template>
</dom-module>
<script>
(function () {
Polymer({
is: 'reddit-list-service',
properties: {
modhash: {
type: String,
value: function() {
return '';
}
},
posts: {
type: Array,
value: function () {
return [];
}
},
after: {
type: String,
value: function () {
return '';
}
}
},
// Update object properties from the ajax call response
handleResponse: function (resp) {
this.properties.modash = resp.detail.response.data.modhash;
this.properties.posts = resp.detail.response.data.children;
this.properties.after = resp.detail.response.data.after;
this.post = this.properties.posts; // just to try
console.log(this.properties.posts);
}
});
})();
</script>
My log shows me that I get posts from the API and that's great!
Here's the issue when I want to use this service to make a list out of the posts array I can't figure out how to get them into my list compoment which is below :
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../reddit-list-service/reddit-list-service.html">
<dom-module id="reddit-post-list">
<template>
<reddit-list-service posts="{{posts}}">
</reddit-list-service>
<template is="dom-repeat" id="post-list" posts="{{posts}}">
<p>{{post.author}}</p>
<template>
</template>
</dom-module>
<script>
(function () {
Polymer({
is: 'reddit-post-list',
properties: {
},
});
})();
</script>
I've tried several think I saw in the documentation but I can't figure out what's wrong the author property doesn't show up.
Any clue?
You have a few things that aren't quite right here. In reddit-post-list you are not using the dom-repeat template correctly. See below:
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="reddit-list-service.html">
<dom-module id="reddit-post-list">
<template>
<reddit-list-service posts="{{posts}}"></reddit-list-service>
<template is="dom-repeat" items="[[posts]]">
<p>{{item.data.author}}</p>
</template>
</template>
</dom-module>
<script>
Polymer({
is: "reddit-post-list"
});
</script>
You need an attribute called items which is the array the dom-repeat will iterate over. Inside the iteration you need to refer to item as this is the array item for the current iteration. Here are the docs.
For you reddit-list-service, you need to set the the reflectToAttribute and notify attributes to true on your posts property. This means that any changes to this property are reflected back on the posts attribute on the reddit-list-service element. See here for more information.
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/iron-ajax/iron-ajax.html">
<dom-module id="reddit-list-service">
<template>
<iron-ajax auto url="https://www.reddit.com/new.json" handle-as="json" on-response="handleResponse"></iron-ajax>
</template>
</dom-module>
<script>
Polymer({
is: "reddit-list-service",
properties: {
modhash: {
type: String,
value: ""
},
posts: {
type: Array,
value: function () {
return [];
},
reflectToAttribute: true, // note these two new attributes
notify: true
},
after: {
type: String,
value: ""
}
},
// Update object properties from the ajax call response
handleResponse: function (resp) {
this.modash = resp.detail.response.data.modhash;
this.posts = resp.detail.response.data.children;
this.after = resp.detail.response.data.after;
}
});
</script>
I have also tidied up the following things:
Removed the immediately called function wrapper from the <script> tags as these are not needed.
When referring to properties in your element you only need to use this.PROPERTYNAME rather than this.properties.PROPERTYNAME.
Having looked at the JSON returned, it appears that the author property is on the another property called data.
When you declare a value for a property in your element, you only need to have a function that returns a value if the property type is an Object or Array.