Can I use iron-localstorage and iron-ajax with highcharts - javascript

I have a polymer element that uses iron-ajax to create a highchart. Could I now incorporate iron-localstorage so the chart will render from the data in ls unless ls is empty in which case it will call iron-ajax to load the data from an api?
My working element is as follows:
<dom-module id="sales-chart">
<template>
<iron-ajax id="ajax" url="{{url}}" last-response="{{data}}"></iron-ajax>
<div id="container" style="max-width: 600px; height: 360px;"></div>
</template>
<script>
Polymer({
is: "sales-chart",
properties: {
url: String,
data: Object
},
observers: [
// These functions only run once the observed properties contain
// something other than undefined.
'_requestData(url)',
'_chartData(data)'
],
_requestData: function(url) {
// Note: Use `generateRequest()` instead of the `auto` property
// because `url` may not be available when your element is
// first created.
this.$.ajax.generateRequest();
},
_chartData: function (data) {
$(this.$.container).highcharts({
chart: {
type: 'spline',
renderTo: 'container'
},
series: [{
data: (data.series)
}]
});
}
});
</script>
</dom-module>

Something along these lines should work (did't test it tough):
<dom-module id="sales-chart">
<template>
<iron-ajax id="ajax" url="{{url}}" last-response="{{data}}"></iron-ajax>
<div id="container" style="max-width: 600px; height: 360px;"></div>
<iron-localstorage name="{{url}}"
value="{{data}}"
on-iron-localstorage-load-empty="_requestData">
</iron-localstorage>
</template>
<script>
Polymer({
is: "sales-chart",
properties: {
url: String,
data: Object
},
observers: [
// These functions only run once the observed properties contain
// something other than undefined.
'_chartData(data)'
],
_requestData: function() {
// Note: Use `generateRequest()` instead of the `auto` property
// because `url` may not be available when your element is
// first created.
this.$.ajax.generateRequest();
},
_chartData: function (data) {
$(this.$.container).highcharts({
chart: {
type: 'spline',
renderTo: 'container'
},
series: [{
data: (data.series)
}]
});
}
});
</script>
</dom-module>

Related

Observing change of a property made within a "brother" polymer element

I have a parent element with 2 child's:
<dom-module id="app-frontend">
<app-frontend-header logoff="{{_logoff}}" current-page="[[_page]]"></app-frontend-header>
<app-frontend-page-profile id="profilepage"
logoff="{{_logoff}}" name="profile">
</app-frontend-page-profile>
Polymer({
is: 'app-frontend',
properties: {
_logoff: {
type: Boolean,
value: false,
notify:true,
},
});
</dom-module>
I'm changing the value of logoff (from false to true) inside header element and I'm trying to run a function in profile element by using an observer
triggerLogoff: function(logoff) {
debugger;
console.log("header " + logoff);
},
observers: [
'triggerLogoff(logoff)'
]
It doesn't want to run (except at the beginning). I can see the property change is observed in the parent element using a similar observer:
triggerLogoff: function(_logoff) {
if (_logoff==true) {
console.log("changed ");
}
},
observers: [
'triggerLogoff(_logoff)'
]
What am I missing?

How to attach nuxeo-tree component to Polymer v1 app

I want to add the <nuxeo-tree> component to my Polymer v1 app, but I'm seeing an error in the console. This is the code I've tried:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/nuxeo-ui-elements/nuxeo-tree/nuxeo-tree.html">
<link rel="import" href="./myVerySpecialLib-import.html">
<dom-module id="my-app">
<template>
tree:<br/>
<nuxeo-tree data="[ title: 'root', children: [ { title: 'a', children: [] }, { title: 'b', children: [ {title: 'x'}, {title: 'y'} ] } ]]]" controller="[[controller]">
<template>
<template is="dom-if" if="[[!opened]]">
<iron-icon icon="hardware:keyboard-arrow-right" toggle></iron-icon>
</template>
<template is="dom-if" if="[[opened]]">
<iron-icon icon="hardware:keyboard-arrow-down" toggle></iron-icon>
</template>
<span select>My title is: [[item.title]]</span>
<span>Am I a leaf? [[isLeaf]]</span>
</template>
</nuxeo-tree>
</template>
<script>
Polymer({
is: 'my-app',
properties: {
data: {
type: String,
value: "[ title: 'root', children: [{ title: 'a',children: []},{title: 'b',children: [{title: 'x'},{title: 'y'}]}]]",
},
opened: {
type: Boolean,
value: true,
},
},
controller: {
// How to get children of a node. Returns a promise.
getChildren: function(node) {
return Promise.resolve(node.children);
},
// Logics you may want to have to control if a node is a leaf.
isLeaf: function(node) {
return node.children.length === 0;
}
},
});
</script>
</dom-module>
And the myVerySpecialLib-import.html file:
controller = {
// How to get children of a node. Returns a promise.
getChildren: function(node) {
return Promise.resolve(node.children);
},
// Logics you may want to have to control if a node is a leaf.
isLeaf: function(node) {
return node.children.length === 0;
}
};
This is the console error:
TypeError: this.controller.isLeaf is not a function
I tried to add the JSON data as a property and also directly into the data field, but neither had a positive effect. How do I fix this?
The myVerySpecialLib-import.html seems to contain a global variable declaration, but that doesn't really help you because <nuxeo-tree> expects controller on the container element (not in a global variable).
Also, your data binding for <nuxeo-tree>.controller is malformed (it's missing a ] at the end):
<nuxeo-tree controller="[[controller]">
And controller probably should be declared as a property if you're binding it. It's currently declared outside the properties object.
// DON'T DO THIS
/*
properties: {...},
controller: {...}
*/
// DO THIS
properties: {
controller: {...}
}
I recommend setting this.controller in the ready() callback of the parent element of <nuxeo-tree> (where this is the container). You could also set <nuxeo-tree>.data via a binding to simplify your HTML template, and that property could be initialized in ready() as well.
ready: function() {
this.data = /* insert data object here */;
this.controller = /* insert controller object here */;
}
demo

Javascript browser inspector console vs source code

This is my problem:
I was playing with ECharts JavaScript library, I wanted to retrieve the image data (I know there is a save as image toolbox). When I try to access the function getDataUrl, or getConnectedDataUrl, I get the following error:
"myChart.getDataUrl is not a function"
But when I try to do the same on the browser (or Firebug) console, I get the info I want. When I call get_data() on the console also get the error I mention before. I'm confused.
What am I doing wrong?
There is the example code:
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<button type="button" onclick="get_data()">holi</button>
<div id="main" style="width:400px;height:300px;"></div>
<script src="echarts.min.js"></script>
<script type="text/javascript">
// based on prepared DOM, initialize echarts instance
var myChart = echarts.init(document.getElementById('main'));
// specify chart configuration item and data
var option = {
title: {
text: 'Test'
},
tooltip: {},
legend: {
data:['Cosas']
},
xAxis: {
data: ["asdf","qwerty","lol"]
},
yAxis: {},
series: [{
name: 'Cosas',
type: 'bar',
data: [1, 3, 5]
}],
toolbox: {
show : true,
feature : {
mark : {show: false},
saveAsImage : {show: true, title: "save"}
}
}
};
// use configuration item and data specified to show chart
myChart.setOption(option);
function get_data(){
return myChart.getConnectedDataUrl();
};
</script>
</body>
</html>
You just misspelled the function names. They are called getDataURL() and getConnectedDataURL() (with uppercase URL).

Access element's property from dom-repeat

I'm using a dom-repeat template in my element, and I want to use the property typeElement of that element (<custom-element>) in a new element (<media-element>) from within dom-repeat:
<dom-module id="custom-element">
<template>
<template is="dom-repeat" items="{{array}}" as="file">
<media-element some-prop="{{typeElement}}" file="{{file}}"></media-element>
</template>
</template>
<script>
Polymer({
is: 'custom-element',
properties: {
typeElement: Number,
array: {
type: Array,
value: function() { return[]; }
}
}
});
</script>
</dom-module>
How can I do that?
I'm not sure what you mean by "use the property", so I'm making assumptions below.
Assuming you want to set <media-element>.someProp to the value of <custom-element>.typeElement, then your data binding is correct. Whenever the value of typeElement changes, someProp will be set to the same value. You could access the value in a method of <media-element> with this.someProp. Example:
<dom-module id="media-element">
<template>...</template>
<script>
Polymer({
is: 'media-element',
properties: {
someProp: Number
},
foo: function() {
console.log(this.someProp);
}
});
</script>
</dom-module>
Assuming you also want the changes to <media-element>.someProp to update <custom-element>.typeElement, then you'd need to set notify: true on the property declaration of someProp:
// media-element
properties: {
someProp: {
type: Number,
notify: true // <-- only needed for upward notifications (two-way data binding and observers)
}
}
HTMLImports.whenReady(() => {
Polymer({
is: 'custom-element',
properties: {
typeElement: {
type: Number,
value: 100,
observer: '_typeElementChanged'
}
},
_typeElementChanged: function(typeElement) {
console.log('new typeElement', typeElement);
}
});
Polymer({
is: 'media-element',
properties: {
someProp: {
type: Number,
notify: true
}
},
_logSomeProp: function() {
console.log('someProp', this.someProp);
},
_incrementSomeProp: function() {
this.someProp++;
}
});
});
<head>
<base href="https://polygit.org/polymer+1.8.1/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<custom-element></custom-element>
<dom-module id="custom-element">
<template>
<media-element some-prop="{{typeElement}}"></media-element>
</template>
</dom-module>
<dom-module id="media-element">
<template>
<button on-tap="_logSomeProp">Log someProp</button>
<button on-tap="_incrementSomeProp">Incremeent someProp</button>
</template>
</dom-module>
</body>
codepen
I recommend reading Polymer Data Binding.
because settings property like:
typeElement: Number won't work. You have to define it like you defined array property. so:
typeElement: {
type: Number,
value: Number,
}
i don't know what value you want to have. After this it should work
Ok i figured myself, the problem isn't here. The problem was on the child element (<media-element>). So i'll post a new question te resolve the problem:
how do the properties of an element been initialized before the element creation? Or, how to trigger the dom-if recalling my condition function after propertie change/init?
My code:
<dom-module id="media-element">
<template>
<template is="dom-if" if="[[isType(0)]]">
....
</template>
</template>
<script>
Polymer({
is: 'media-element',
properties: {
myType: {
type: Number,
value: 0
}
},
isType: function(t){return (this.myType===t);}
});
</script>
</dom-module>
UPDATE: I sent my question and receive a goode answer: here

Polymer dom-repeat sub property changes child to host wiring

I have a host element binding array of object to child element which has a paper-input to edit its properties. I don't see the value change on input reflected in the host div element. Even though on debug I can see that the host object has the latest edited name. What should I do to get this automatically wired ?
<!-- Host element -->
<dom-module id="host-item">
<template>
<div>
<div>[[selectedEmployee.name]]</div>
<template is="dom-repeat" items="[[employees]]" as="employee">
<item-edit item="[[employee]]"></item-edit>
</template>
</div>
</template>
<script>
Polymer({
is: 'host-item',
properties: {
selectedEmployee: {
type: Object
},
employees: {
type: Array,
value = [ { name: 'Name 1'}, { name: 'Name 2'}, { name: 'Name 2'}]
}
},
ready: function() {
this.selectedEmployee = this.employees[0];
}
});
</script>
</dom-module>
<!-- Child element -->
<dom-module id="item-edit">
<template>
<paper-input id="input" value="{{item.name}}" error-message="Invalid name!"></paper-input>
</template>
<script>
Polymer({
is: 'item-edit',
properties: {
item: {
type: Object
}
}
});
</script>
</dom-module>
Use {{employee}} for 2 way binding. [[...]] is for one way only.
Use notify: true on property definition.
Child element should be defined before the parent.
Here is the working example Plunk, and similar Plunk
<item-edit item="{{employee}}"></item-edit>
...
employee: {
type: Object,
notify: true,
value: function () { return {name: 'Test' }; }
}
Update:
Now "employees" data is in form of an array of objects.
Check out this question for working with arrays:
Polymer, issue with binding array to paper slider value
Plunk
Docs: Binding to array items

Categories