Reputation: 240
I created a custom element called my-slider-input which computes values from a user input. I need to take use these values in an angular controller. I'm wondering what's the best practice to do this?
Given this polymer element:
<dom-module id="my-slider-input">
<style>
:host {
display: block;
}
</style>
<template>
<button id="input1">Input 1</button>
<button id="input2">Input 1</button>
<button id="input3">Input 1</button>
</template>
</dom-module>
<script>
(function() {
Polymer({
is: 'my-slider-input',
properties: {
value: {
type: Object,
computed: 'computeOutputs()',
reflectToAttribute: true,
notify: true
},
output1: {
type: Number,
reflectToAttribute: true,
notify: true
},
output3: {
type: Number,
reflectToAttribute: true,
notify: true
},
output2: {
type: Number,
reflectToAttribute: true,
notify: true
}
},
listeners: {
'input1.down': 'computeOutputs',
'input2.down': 'computeOutputs',
'input3.down': 'computeOutputs'
},
attached: function() {
//Fired when this component is attached.
this.computeOutputs();
},
computeOutputs: function() {
var aggregateValue = {};
this.output1 = this.complexFunction(1);
this.output2 = this.complexFunction(2);
this.output3 = this.complexFunction(3);
aggregateValue.output1 = this.output1;
aggregateValue.output2 = this.output2;
aggregateValue.output3 = this.output3;
return aggregateValue;
},
complexFunction: function(input) {
//some complex calculations
return 1;
}
});
})();
</script>
I want to get the outputs of my-slider-input, I know I can create/listen for event notifications. How can I get the output for an angularjs controller?
How do I do something like this?
<div ng-Controller="myController">
<my-slider-input value="{{outputAggregateValue}}"></my-slider-value>
</div>
or
Should I do something like this?
<div ng-Controller="myController">
<my-slider-input output1="{{output1}}" output2="{{output2}}" output1="{{output3}}"></my-slider-value>
</div>
Currently in either scenario, the $scope values are not updated.
If this isn't the best way (2-way vs 1-way), how do I get the output out of my custom element and work with it in my controller?
Here's a jsbin link: http://jsbin.com/kosetiyelu/edit?html,output
Thanks in advance! -Dan
Upvotes: 1
Views: 1630
Reputation: 111
I am using ng-polymer-elements to do what you describe, it supports many polymer components out of the box and provides an easy way to add your own mappings for custom/other unsupported components.
Check here: https://gabiaxel.github.io/ng-polymer-elements/
From their documentation: "There are two cases where you can't get Web Components to work with your AngularJS models:
<paper-input value="{{myModel}}"></paper-input>
will not change myModel when the user changes the input text.<google-map map="{{myMap}}"><google-map>
will not work because the expression {{myMap}} will be treated as a string.
Enters ng-polymer-elements."Upvotes: 1
Reputation: 2782
I believe it is best to use the angular-bind-polymer
directive from here. The code is already written and it is working, so no need for you to implement it by yourself.
Instructions from the aforementioned page:
This will only work if the Polymer element publishes and reflects attributes. That is, it is insufficient to declare attributes:
To mark the out attribute as reflectable, declare it as such with the publish property:
Your element should therefore look like this:
<polymer-element name="x-double" attributes="in out">
<template><!-- ... --></template>
<script>
Polymer("x-double", {
publish: {
out: {value: 0, reflect: true}
},
// ...
});
</script>
</polymer-element>
After that, just add the bind-polymer
to your custom elements within the HTML code.
EDIT: Since the author is using Polymer 1.0, I have found another tutorial for passing data from Polymer to Angular: http://jcrowther.io/2015/05/26/using-polymer-webcomponents-with-angular-js/. In this tutorial, angular-bind-polymer
is also used so I don't think the plugin is Polymer 0.5 specific.
EDIT 2: I have now noticed that the above tutorial does not use Polymer 1.0, but Polymer 0.9.
Upvotes: 1
Reputation: 11027
I can only help you with the Polymer side of your question, but here goes.
The code in your question looks like proper Polymer 1.0 code, but the code in the JS Bin is mixed up between Polymer 0.5 and 1.0. @alesc's answer is only for 0.5, so there is version confusion.
Fwiw, here is a JsBin with proper Polymer 1.0 code: http://jsbin.com/vevawi/edit?html,output
If you examine the output you can see that Polymer is reflecting the values back to the attributes as requested. As for why Angular is not picking them up, I can't help you.
Fwiw, because of the notify: true
settings, Polymer is also sending property-change events. Specifically, the my-slider-input
is sending object1-changed
, object2-changed
, object3-changed
, and value-changed
(non-bubbling) events. Maybe you can use those to update the values in the Angular scope.
Upvotes: 1