Passing attribute to custom element in Polymer as a function - polymer

I'm trying to do something really simple in Polymer. I'm trying to pass an attribute using a function.
<dom-module id="my-fixtures">
<template>
<fixtures-list fromdate="[[_requiredDay(24)]]"></fixtures-list>
</template>
<script>
Polymer({
is : 'my-fixtures',
properties: {
fromdate: String
},
_requiredDay: function (offset) {
// 1 day before now
var d = new Date(new Date().getTime() - parseInt(offset) * 60 * 60 * 1000);
var n = d.toJSON();
return n;
}
});
</script>
</dom-module>
But it' not working. If I change the function for a static srting value it works. Any help?
Thanks

The fromdate property should be on fixtures-list not on my-fixtures
https://jsbin.com/jucevujeyo/edit?html,console,output

Related

Assigning value to variables in polymer

Polymer doesn't bind data if we assign value to polymer multiple times.
For example:
Polymer({
is: "g-feed",
properties: {
event: String
},
ready: ()=> {
var self = this;
self.news = [];
var nws = [];
nws.push({nm:'One'});
nws.push({nm:'Two'});
self.news = nws;
nws.push({nm:'One1'});
nws.push({nm:'Twoa'});
self.news = nws;
console.log(self.news);
}
});
Here the news array would only hold the values "one" and "two" rendered on the webpage.
Can you please tell me why this happens and how to overcome this. Also, how to work with consistantly changing data in polymer.
Thanks.

Can not stub private element in WCT

Using Polymer 1 and Web component tester... testing in shady dom on chrome.
In WCT, trying to stub spToast.display() with stub('sp-toast', { display: ()=> {} }); but I get error with Attempted to wrap undefined property display as function.... what I am doing wrong?
The reason why I am trying to stub it is because I get spToast.display is not a function when the test runs the code base.
original code:
showAgeWarning: function() {
var spApp = Polymer.dom(document).querySelector('sp-app');
var spToast = Polymer.dom(spApp.root).querySelector('sp-toast');
var msg = "foo"
spToast.display('information', msg);
},
test code:
<test-fixture id="sp-veteran">
<template>
<h2>edit veteran</h2>
<sp-app>
<sp-toast></sp-toast>
<sp-veteran>
</sp-veteran>
</sp-app>
</template>
</test-fixture>
setup(function() {
replace('sp-app').with('fake-sp-app');
replace('sp-ajax').with('fake-sp-ajax');
stub('sp-value-dropdown', { setInvalidState: (state)=> {} });
myEl = fixture('sp-veteran');
});
test('it should validate the veteran', function() {
var spApp = Polymer.dom(myEl.root).querySelector('sp-app');
var spToast = Polymer.dom(spApp.root).querySelector('sp-toast');
sinon.stub(spToast, 'display');
When you get Attempted to wrap undefined property display as function it means that it can't replace a method that doesn't exist (yet).
If you actually get a value for var spToast = Polymer.dom(spApp.root).querySelector('sp-toast') in your test, and nothing about your test is going to give display a value, you could just set it, a la spToast.display = function() {}; then you should be able to set a spy on it or what have you as needed.
Put it all together and you could have
test('it should validate the veteran', function() {
var spApp = Polymer.dom(myEl.root).querySelector('sp-app');
var spToast = Polymer.dom(spApp.root).querySelector('sp-toast');
spToast.display = function() {};
sinon.spy(spToast, 'display');
// Trigger the side effect that would lead to `display` being called
assert.equal(
spToast.display.calledOnces,
true
);
});

declaring a function in polymer

I'm trying to use a function within another, but even though I declared it beforehand, polymer says it isn't. I don't get it. any clue?
Polymer({
is: 'x-foo',
//some other code here, including the properties....
computeRange: function (offset, limit, nodeRangeStart, nodeRangeEnd) {
nodeRangeStart.innerText = offset;
nodeRangeEnd.innerText = offset + limit;
},
prevPage: function () {
this.offset = this.offset - this.limit;
computeRange(this.offset, this.limit, this.$.usersListRangeStart, this.$.usersListRangeEnd);
this.$.nextPage.removeAttribute('disabled');
if (this.offset <= 0) {
this.$.prevPage.setAttribute('disabled', true);
this.$.prevPage.style.color = '#DDDDDD';
};
}
});
and the console:
Uncaught ReferenceError: computeRange is not defined
You're attempting to call computeRange() as if it were a global function, but it's actually part of your constructor object. You'll need to use this:
this.computeRange(...)

How do I get the value assigned to on-click in paper-button?

I need this for custom element that can decorate event handlers e.g. for showing a confirmation dialog when you click on a button. Specifically, I need to know the name of event handler to be able to remove it with this.unlisten and define a wrapper for it.
There's currently no public API for this, but you could use the following code, which reaches into Polymer internals to get at the bound event listeners. Since it uses Polymer's private API, this solution isn't guaranteed to work in future releases.
In Polymer 1.5.0, event listeners are added to an internal property __boundListeners, which is a map of event names to method names. The format of the keys in this map is "<eventName>:<methodName>" (e.g., "tap:_handleTap"). So, you'd be able to find all methods that listen to a particular event by searching __boundListeners:
function getListenerMethods(target, eventName) {
var boundListeners = this.__boundListeners || {};
var listeners = boundListeners.get(target) || {};
var methodNames = Object.keys(listeners).filter(function(key) {
return key.split(':')[0] === eventName;
}).map(function(key) {
return key.split(':')[1];
});
return methodNames;
},
In the demo below, I used a mixin on Polymer.Base to add unlistenAll(), which allows you to use the function from your Polymer object like this:
this.unlistenAll(this.$.myButton, 'click');
Here's the demo:
<head>
<base href="https://polygit.org/polymer+1.5.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="paper-button/paper-button.html">
</head>
<body>
<x-foo></x-foo>
<script>
HTMLImports.whenReady(function() {
// Mixin
Polymer.Base._addFeature({
/**
* Gets the names of all methods listening to an element's event.
*
* #param {Element} target Node element to retrieve method names from.
* #param {String} eventName Name of event to look up.
* #returns {Array} names of handler methods on `this`
*/
getListenerMethods: function(target, eventName) {
var boundListeners = this.__boundListeners || {};
var listeners = boundListeners.get(target) || {};
var methodNames = Object.keys(listeners).filter(function(key) {
return key.split(':')[0] === eventName;
}).map(function(key) {
return key.split(':')[1];
});
return methodNames;
},
/**
* Removes all listeners of a specific event from a given element.
*
* #param {Element} target Element to remove event listener from.
* #param {String} eventName Name of event to stop listening to.
*/
unlistenAll: function(target, eventName) {
var self = this;
this.getListenerMethods(target, eventName).forEach(function(methodName) {
console.log('unlistening "' + eventName + ':' + methodName + '" from:', target);
self.unlisten(target, eventName, methodName);
});
}
});
});
</script>
<dom-module id="x-foo">
<template>
<paper-button id="btn" on-click="_click">click</paper-button>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-foo',
_click: function() {
console.log('clicked');
},
ready: function() {
this.unlistenAll(this.$.btn, 'click');
}
});
});
</script>
</dom-module>
</body>
codepen

How To Access Polymer Custom Element From Callback

I need to access the custom element and call its method from the click event callback.
<polymer-element name="my-element">
<template>
<style type="text/css" media="screen">
...
</style>
<ul id="my_data"></ul>
</template>
<script>
Polymer('my-element', {
dataSelected: function(selectedText) {
//...
},
setData: function(data) {
for (var i = 0; i < data.length; i++) {
var li = document.createElement('li');
li.addEventListener('click', function(e) {
// how can I call dataSelected() from here?
});
li.innerText = data[i];
this.$.my_data.appendChild(li);
}
}
});
</script>
</polymer-element>
How can I call the custom element's dataSelected() method from the callback?
You can use bind to attach a this context to any function, so:
li.addEventListener('click', function(e) {
this.dataSelected(e.target.innerText);
}.bind(this));
http://jsbin.com/xorex/4/edit
But you can make things easier by using more Polymer sugaring. For example, you can publish data and use the observation system, like so:
<polymer-element name="my-element" attributes="data">
...
data: [], // type hint that data is an array
...
dataChanged: function() { // formerly setData
http://jsbin.com/xorex/5/edit
Also, you can use the built-in event system instead of addEventListener
<polymer-element name="my-element" attributes="data">
...
<ul id="my_data" on-tap="{{dataTap}}"></ul>
...
dataTap: function(e) { // `tap` supports touch and mouse
if (e.target.localName === 'li') {
this.dataSelected(e.target.textContent);
}
}
http://jsbin.com/xorex/6/edit
But the biggest win is using <template repeat> instead of creating elements in JavaScript. At that point, the complete element can look like this:
<polymer-element name="my-element" attributes="data">
<template>
<ul id="my_data">
<template repeat="{{item in data}}">
<li on-tap="{{dataTap}}">{{item}}</li>
</template>
</ul>
</template>
<script>
Polymer('my-element', {
data: [],
dataTap: function(e) {
console.log('dataSelected: ' + e.target.textContent);
}
});
</script>
</polymer-element>
http://jsbin.com/xorex/7/edit
You could insert element = this; at the beginning of your setData() function and call element.dataSelected(); in the event handler.
But i think for what you want to achieve, you'd better use a repeat template (Iterative templates) and a direct binding to your click handler function (Declarative event mapping).