My Goal
I want to remove all the 1 values from the items property (2d array) shown in this jsBin by pressing the Clear button.
Steps to recreate the problem
Open this jsBin.
In the output pane, press the Show button.
Look in the console, notice the logged output:
"Items: Lorem,Ipsum,foo,1,bar,1,baz,0,qux,0"
In the output pane, press the Clear button.
Look in the console, notice the logged output is the same as before:
"Items: Lorem,Ipsum,foo,1,bar,1,baz,0,qux,0"
What I expect to see...
In the last step described above, in the console, I expect to see the following logged to the console:
Lorem,Ipsum,foo,0,bar,0,baz,0,qux,0
What I actually see...
Instead, as already described, I see:
Lorem,Ipsum,foo,1,bar,1,baz,0,qux,0
Note the lack of agreement between the HTML rendered on the screen and the logged value is addressed by this SO question. (This question is not a duplicate for reasons described below.)
Question
How do I successfully update the value of the items variable to:
[['Lorem','Ipsum'],['foo',0],['bar',0],['baz',0],['qux',0]]?
(Please show a working jsBin if possible.)
Code
http://jsbin.com/wabebituvi/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<button on-tap="_show">Show</button>
<button on-tap="clearAll">Clear</button>
<div>{{selected}}</div>
<div>{{items}}</div>
</template>
<script>
(function(){
Polymer({
is: 'x-element',
properties: {
items: {
type: Array,
notify: true,
reflectToAttribute: true,
computed: '_computeItems(selected)',
value: function() {
return [['Lorem', 'Ipsum'], ['foo', 0], ['bar', 0], ['baz', 0], ['qux', 0],];
}
},
selected: {
type: Array,
notify: true,
reflectToAttribute: true,
value: [],
},
},
_computeItems: function(a) {
var out = this.items,
selectedLength = a.length,
i = out.length;
while(i---1){
var j = selectedLength;
while(j--) {
if(a.indexOf(out[i][0])===-1){
out[i][1] = 0;
}
else if(a.indexOf(out[i][0])>-1){
out[i][1] = 1;
}
else {
console.log('Error: Undefined index of selected item');
}
}
}
return out;
},
_computeSelected: function(a) {
var out = [],
i = a.length;
while(i---1){
if(a[i][1]){out.push(a[i][0]);}
}
return out.sort();
},
ready: function(){
this.set('items', this._computeItems(this.seletcted));
},
clearAll: function() {
this.set('selected', []);
this.set('items', this._computeItems(this.selected));
},
_show: function() {
console.log('Selected: ' + this.selected);
console.log('Items: ' + this.items);
},
});
})();
</script>
</dom-module>
<x-element
selected='["foo","bar"]'
></x-element>
</body>
Reasons why this question is not a duplicate:
The code is similar, but not the same. And the questions are also similar but different. The solutions, I suspect, are probably related and might be the result of whatever I'm not understanding. The alternative: Asking both questions in a single post, I fear would be too complicated to receive effective answers. So I am opting to try to separate the issues into separate questions to help others understand and provide clearer answers. And finally, this is my attempt to provide a minimal example. I've trimmed out a lot of code
The code in your jsbin gives me an error:
"TypeError: Cannot set property items of #<x-element> which has only a getter
and I had to comment out:
this.set('items', this._computeItems(this.selected));
to stop it.
From what I see, your _computeSelected function never clears, because after setting selected to [], selectedLength is equal 0 and your inner loop never evaluates.
I've added some code to reset those counters to 0 before entering the while loops and it seems to work:
_computeItems: function(a) {
var out = this.items,
selectedLength = a.length,
i = out.length;
out.forEach(function(pair) {
if (Number.isInteger(pair[1])) {
pair[1] = 0;
}
});
while(i---1){
var j = selectedLength;
while(j--) {
if(a.indexOf(out[i][0])===-1){
out[i][1] = 0;
}
else if(a.indexOf(out[i][0])>-1){
out[i][1] = 1;
}
else {
console.log('Error: Undefined index of selected item');
}
}
}
return out;
},
Console output:
"Selected: foo,bar"
"Items: Lorem,Ipsum,foo,1,bar,1,baz,0,qux,0"
"Selected: "
"Items: Lorem,Ipsum,foo,0,bar,0,baz,0,qux,0"
I am trying to create a behavior that adds a computed property to the element it augments.
Example Template:
<template>
<span>[[getLight(0)]]</span><br />
<span>[[getLight(1)]]</span><br />
<span>[[getLight(2)]]</span><br />
</template>
<script>
Polymer({
is: 'vertical-light',
behaviors: [
stopLightBehavior
]
});
</script>
Example Behavior:
//Located in another file, with its implementation obscured
stopLightBehavior = {
ready: function() {
this._myArray = [true, false, false];
setInterval(function() {
this.unshift('_myArray', this.pop('_myArray'));
// getLight needs to be updated!
}.bind(this), 500);
},
getLight: function(index) {
return this._myArray[index];
}
};
In the above example, the values like getLight(0) never get updated because they don't reference _myArray.*. However, I don't want the users of the behavior to have to enumerate the dependencies of getLight every time. Is it possible to tell Polymer exactly when getLight needs to be updated?
I have a problem with Polymers iron-ajax element.
When calling it like this:
<iron-ajax url="https://api.onedrive.com/v1.0/drive/root" params='{"access_token":"[[access_token]]"}'></iron-ajax>
It sends a url like this, splitting the whole params string into multiple parameters:
https://api.onedrive.com/v1.0/drive/root?0="&1=a&2=c&3=c&4=e&5=s&6=s&7=_&8=t&9=o&10=k&11=e&12=n&13="...
When using a normal String as parameter it works correctly so i guess the quotes are correct.
The script part of the Element which uses iron-ajax:
<script>
Polymer({
is: 'onedrive-files',
properties: {
access_token: String
},
ready: function() {
},
});
</script>
and i am calling the element like this:
<onedrive-files access_token="testtoken">
</onedrive-files>
Does anyone have any ideas?
Thanks!
Edit:
With an getter Function:
<dom-module id="onedrive-files">
<template>
<iron-ajax id="ajax" url="https://api.onedrive.com/v1.0/drive/root" last-response="{{data}}" params='{{_getParams()}}' auto></iron-ajax>
</template>
<script>
Polymer({
is: 'onedrive-files',
properties: {
access_token: String
},
_getParams: function()
{
return ('{"access_token":"' + this.access_token + '"}');
},
ready: function() {
this.$.ajax.generateRequest();
},
});
</script>
</dom-module>
With setting the Param in the Ready function:
<dom-module id="onedrive-files">
<template>
<iron-ajax id="ajax" url="https://api.onedrive.com/v1.0/drive/root" last-response="{{data}}" auto></iron-ajax>
</template>
<script>
Polymer({
is: 'onedrive-files',
properties: {
access_token: String
},
ready: function() {
this.$.ajax.params = '{"access_token":"' + this.access_token + '"}';
},
});
</script>
</dom-module>
It seems like this is another limitation of dynamic attributes. So, the usual fallback for such cases are getter functions :
<iron-ajax url="https://api.onedrive.com/v1.0/drive/root" params='{{_getParams(access_token)}}'></iron-ajax>
...
<script>
Polymer({
is: 'onedrive-files',
properties: {
access_token: String
},
_getParams:function(access_token) {
return {access_token:access_token};
}
});
</script>
The params property is an Object, and it looks like the parsing from the html attribute (which is String) only happens on attached.
IMHO the easiest solution is to set it before you generate the request.
But set an Object, not an String. It will generate one GET param foreach element of the params Object, a String is a list of characters, so one GET param for each character...
this.$.myAjaxElement.set( 'params', {"access_token": this.access_token });
this.$.myAjaxElement.generateRequest();
I'm having issues with the monostate pattern in Firefox 35, using Polymer 0.5.2. My element looks like this:
<polymer-element name="tracer-globals">
<script>
(function() {
var store = document.createElement('tracer-store');
Polymer({
publish: {
store: null
},
ready: function() {
this.store = store;
}
});
})();
</script>
</polymer-element>
In Chrome at the point of ready I can see the various attributes of the store object, but on Firefox, the attributes are never defined (even long after the app has finished loading).
Any ideas why?
Things I've tried:
Ensure tracer-store is imported before tracer-globals.
Found a workaround:
Lazy-load the global object in the created callback:
<polymer-element name="tracer-globals">
<script>
(function() {
var store = null;
var getStore = function() {
if (store === null) {
store = document.createElement('tracer-store');
}
return store;
};
Polymer({
publish: {
store: null
},
created: function() {
this.store = getStore();
}
});
})();
</script>
</polymer-element>
Would appreciate comments as to why this works.
I need some help with the chrome.windows.create function in javascript I just cant seem to work it out
Heres the html file:
<html>
<head>
<script>
function load() {
chrome.windows.create({ url: 'http://www.google.com', type: 'panel' });
}
</script>
</head>
<body onLoad="load()">
</body>
inline javascript codes are not allowed (by default) in chrome extensions. so you have to change the code like this.
<html>
<head>
</head>
<body>
</body>
<script src="loader.js"></script>
loader.js:
function load() {
chrome.windows.create({ url: 'http://www.google.com', type: 'panel' });
}
document.getElementsByTagName( 'body' )[0].onload = function() { load(); };
For more information about content-security policies visit: Content Security Policy (CSP) - Google Chrome