I'd like to use a shared function for computed bindings in different custom elements. Is this possible?
No matter how I import the shared function, I get console errors:
method `formatAmount` not defined
The computed binding is something like:
<span>[[formatAmount(amount)]]</span>
I've tried using a tag above the element. I've tried inside the element. And I've tried in index.html.
Do all computed binding methods need to be defined in the custom element and can't be shared? Do I have to use a mixin?
UPDATE: I've created an ugly work around where I define a private method on my custom element that calls the shared method. Then the private method is used in the computed binding. This is ugly because of the extra boilerplate.
...
<script src="format-amount.js"></script>
<dom-module id="my-foo">
<template>
...[[_formatAmount(amount)]]...
</template>
<script>
class MyFoo extends Polymer.Element {
...
_formatAmount(amount) {
return formatAmount(amount); // Defined in format-amount.js.
}
}
</script>
</dom-module>
This is similar question to what I have asked few months ago.
You can use mixin. A mixin is simply a function that takes a class and returns a subclass. If you want to learn more click here.
For your problem define mixin in separate html file say - my-mixin.html:
const MyMixin = (superClass) => class extends superClass {
constructor() {
super();
}
formatAmount(amount) {
//function contents
}
}
And then in your element import and add mixin:
<link rel="import" href="my-mixin.html">
class MyFoo extends MyMixin(Polymer.Element)
Then you can simply call the function from your element:
<template>
...[[formatAmount(amount)]]...
</template>
To access the function in script use super.formatAmount(amount).
Related
I am experimenting with Polymer 2.x and what I don't understand is how to use Polymers own behaviors in Polymer 2.x, iron-resizable-behavior as an example.
The Polymer 2.0 upgrade guide tells us that for our own components we should work with class expression mixins. That's fine but what about Polymers own behaviors? Are they in the progress of being rewritten as mixins or will they remain unchanged? There is a Polymer.mixinBehaviors method that seems to allow me to use Polymer 1.x mixins. Is this the final solution or is this an intermediate step?
To phrase it another way: are the Polymer behaviors considered Polymer 2.x although we are told to use mixins for our own components?
Sources:
https://www.polymer-project.org/2.0/docs/upgrade#upgrading-to-class-based-elements
Applying Behaviors with JS Mixins in Polymer 2
class MyElement extends Polymer.mixinBehaviors([Polymer.IronFormElementBehavior], Polymer.Element) { ... }
I think Polymer has an API for that. I think it is dedupingMixin.
Below is an example how to create a mixin for your own behavior and how to use it in your element class.
var MyBehaviorMixin = Polymer.dedupingMixin(function(superClass){
return class MyBehavior extends superClass {
constructor() {
super();
}
methodInBehavior() {
return "this method is defined in Behavior";
}
}
}
class MyElement extends MyBehaviorMixin(Polymer.Element){
constructor(){
super();
console.log(this.methodInBehavior());
}
}
So I found a way how to use the iron-resizable-behavior in Polymer2
Instead of using the Mixin I am making use of the syntax of codeMonkey and extended his answer to show how to use it
As far as I know, this solution is a hybrid for Polymer 1 & 2
class customElement extends Polymer.mixinBehaviors([Polymer.IronResizableBehavior], Polymer.Element) {
static get is() { return 'custom-element'; }
ready() {
super.ready();
this.addEventListener('iron-resize', () => { this.onWidthChange() });
}
onWidthChange() {
var w = this.offsetWidth;
if (w > 0)
console.log("Width of page is now ", w);
}
}
I am trying to call a function inside child component through this.refs but i keep getting error that this function doesn't exist.
Uncaught TypeError: this.refs.todayKpi.loadTodaysKpi is not a function
Parent component:
class KpisHeader extends React.Component {
constructor() {
super();
this.onUpdate = this.onUpdate.bind(this);
}
render(){
return <div>
<DateRange ref="dateRange" onUpdate={this.onUpdate}/>
<TodayKpi ref="todayKpi" {...this.state}/>
</div>;
}
onUpdate(val){
this.setState({
startDate: val.startDate,
endDate: val.endDate
}, function(){
this.refs.todayKpi.loadTodaysKpi();
});
}
}
I want to get some data from DateRange component through function onUpdate, and then I want to trigger a function inside TodayKpi which fetches data from the server. For now it is just console.log("AAA");.
Child component:
class TodayKpi extends React.Component {
constructor() {
super();
this.loadTodaysKpi = this.loadTodaysKpi.bind(this);
}
render(){
console.log(this.props.startDate + " "+ this.props.endDate);
return <div className="today-kpi">
</div>;
}
loadTodaysKpi(){
console.log("AAAA");
}
}
How should I implement this?
For reasons I don’t yet grasp, React discourages calling child methods from the parent. However, they relent and give us an ‘escape hatch’ which allows just that. You were correct in thinking that ‘Refs’ were a part of that escape hatch. If, like me, you have read dozens of articles searching for this information, you will be well prepared to understand their description of the escape hatch
In your case, you may want to try something like this in your KpisHeader class.
Change this line
<TodayKpi ref="todayKpi" {...this.state}/>
to use a ref callback function something like this:
<TodayKpi ref={(todayKpiComponent) => this.todayKpiComponent = todayKpiComponent} {...this.state}/>
or, pre-ES6, this:
<TodayKpi
ref=
{
function (todayKpiComponent)
{
this.todayKpiComponent = todayKpiComponent
}
}
{...this.state}
/>
Then you will be able to access your todayKpi component methods from your KpisHeader class like this:
this.todayKpiComponent.someMethod();
Oddly, for me, inside the ref callback function, ‘this’ was the window rather than the parent component. So, I had to add
var self = this;
above the render method and use ‘self’ inside the ref callback function.
In my case I had an unknown number of dynamically generated children components, so I put each one into an array. I cleared the array in componentWillUpdate. It all seems to be working but I have an uneasy feeling especially given React’s distaste for calling children’s methods.
If you want the function/method to be called inside the child, you should pass it to the child from the parent to start with. The other thing that you need to change is onUpdate to onChange, assuming that you want to track every change to that field. The other alternative is to check when it is onSubmit, but it sounds like you want to have it happen every time the field is updated.
I am building a Polymer web component that should respond to mouse/touch events. I would like to bind the on-tap="{{$.myElement.show}}" where show is a function in the element:
show: function(e) {
// Do something with the event here
}
Is there anyway to define a public API in Polymer. The route I am going at the moment is to have attributes="event" on the element then the parent element has on-tap="{{updateEvent}}":
updateEvent: function(e) {
this.$.myElement.event = e;
}
The element then just has:
eventChanged: function() {
show(this.event);
}
Which just seems boilerplaty (think that is a made up word). Can I add the show function to the element prototype somehow?
If show() is a method on your element, just use on-tap="{{show}}". show() is part of the element's public APi.
But it looks like you want is to call another element's method? This came up recently in a pull request: https://github.com/Polymer/polymer-dev/pull/30
What you have with setting this.$.myElement.event = e; and using eventChanged() in myElement works. You can also just call the element's method directly:
updateEvent: function(e) {
this.$.myElement.show();
}
Here are a few other ways: http://jsbin.com/guyiritu/1/edit
I'm having a slight issue with ActionScript 3 and I have come here to ask for some help.
I have two classes. One called Sledge and one called Sock, there is also the document class called Main.
My issues are as follows:
Inside of Sledge, I call a function that is defined inside of the Main document class. How would I go about telling the class to go to the document class and run that function? Would this also be the same for other classes or just for the document class?
Inside Sledge, I have the following statement: if(hitTestObject(sock.myHitArea)) { /* somecode*/ }
sock is an instance of another seperate class, and by this point has already been created. However when I try and run this I am told it is not defined. How would i go about solving this?
There's some ambiguity issues with how you expressed your question. It would help if you posted a short form of the code for the problem.
However, I'll try to answer the first question:
Inside of Sledge, I call a function that is defined inside of the Main document class. How would I go about telling the class to go to the document class and run that function?
You would want to pass the Main class to the Sledge class or use events which is preferable. If pass the class it will look like this...
class Sledge {
private var main:Main;
function Sledge(main:Main) {
this.main = main;
}
function doSomething():void {
main.runSomeFunction();
}
}
Or if using events:
class Main {
private var sledge:Sledge;
function Main() {
sledge = new Sledge();
sledge.addEventListener("mainDoSomething", doSomething);
}
private function doSomething(e:Event):void {
// .... do stuff
}
}
class Sledge extends EventDispacter {
function Sledge() {
}
public function doSomething():void {
dispatchEvent(new Event("mainDoSomething"));
}
}
I develop with FlashDevelop3 R2 and the Flex 3.3 SDK and there are many occasions where I must use the embed metadata tag as such:
[Embed(source="path/to/file")]
private var Asset:Class;
I understand the above all well and good, and I am thankful it exists because I do not like to open the flash IDE too often.
When I am going through other authors classes lately, I have found an interesting metadata tag that I do not understand:
[Event(name="", type="")]
I have yet to see a situation where I require this, and furthermore I really just do not understand what it is for.
Thank in advance for your help.
Brian Hodgeblog.hodgedev.com hodgedev.com
These [Event(name, type)] declarations describe which events a class instance is likely to dispatch.
They are actually useful for code completion - for instance when you type: mySprite.addEventListener(, your code editor (Flex Builder or FlashDevelop) will display a meaningful list of events that this object can dispatch.
So you can add these declarations in your code and benefit from a richer code completion.
Also note that this works with custom Event classes (see FlashDevelop's new Event class template).
package mycomp {
import flash.events.Event;
public class MyEvent extends Event {
public const SOME_EVENT:String = "someEvent";
// required Event type declarations
}
}
package mycomp {
[Event(name="someEvent", type="mycomp.MyEvent")]
public class MyComp extends Sprite {
}
}
package myproject {
import mycomp.MyComp;
public class MyProject {
function MyProject() {
var mc:MyComp = new MyComp();
mc.addEventLister( //completes: SOME_EVENT + Sprite events
}
}
}
We use it for binding custom events to our custom MXML components. This tag allows you to reference it from MXML. See documentation:
[Event(name="enableChanged", type="flash.events.Event")]
class ModalText extends TextArea {
...
}
<MyComp:ModalText enableChanged="handleEnableChangeEvent(event);"/>
The compiler will complain, however, if you try to refer to an event on an mxml tag that was not declared with an event metatag.