Passing a function as an attribute value - polymer

I was wondering if it was possible to pass a function foo() as an attribute func="foo()" and have it called this.func() inside of the polymer element?
<foo-bar func="foo()"></foo-bar>
Polymer({
is: 'foo-bar',
properties: {
func: Object,
},
ready: function() {
this.func();
}
});
I've been trying to get this working for ages with no luck.
Thanks in advance.

<foo-bar func="foo()"></foo-bar>
Polymer({
is: 'foo-bar',
properties: {
func: {
type: String, // the function call is passed in as a string
notify: true
},
attached: function() {
if (this.func) {
this.callFunc = new Function('return '+ this.func);
this.callFunc(); // can now be called here or elsewhere in the Polymer object
}
});
So the trick is that "foo( )" is a string when you first pass it to the Polymer element. I fought with this for a while as well and this is the only way I could find to get it done. This solution creates a function that returns your function call, which you assign as the value of one of your polymer element properties.
Some people might say you shouldn't use the Function constructor because it is similar to eval( ) and.... well you know, the whole 'eval is evil' thing. But if you're just using it to return a call to another function and you understand the scope implications then I think this could be an appropriate use-case. If I'm wrong I'm sure someone will let us know!
Here's a link to a nice SO answer about the differences between eval( ) and the Function constructor in case it can help: https://stackoverflow.com/a/4599946/2629361
Lastly, I put this in the 'attached' lifecycle event to be on the safe side because it occurs later than 'ready'. I'm not sure if an earlier lifecycle event or 'ready' could be used instead of 'attached'. Perhaps someone can improve this answer and let us know.

Related

pass a local variable to an click function

I want to pass a local variable from one function to another and I have tried some solutions but they didn't work because I have a click function, I need to put the variable first of all and I don't how to do it, also I declared the variable outside the function but if I use it outside of all the functions it doesn't has all its values or inside the function resaltar nothing appears, any help is welcome
let children=$('div[class^="fila"], div[class^="pieceRow"]' ).children()
var clase
$(children).each(function getClass(){
clase=$(this).attr('class')
$(clase).on('click', function resaltar(){
if (clase==clase) {
$(this).addClass('shadow')
}
})
})
this is the html code https://jsfiddle.net/qb5fwcus/
Please try this code :
let children = $('div[class^="fila"], div[class^="pieceRow"]' ).children();
$(children).on('click', function(){
var clase = $(this).attr('class');
resaltar(clase);
})
function resaltar(clase){
$('.shadow').removeClass('shadow');
$('.' + clase).addClass('shadow');
}
Explanation : You can not pass any value for the callback function for any event handler. Either it can be an anonymous function, or a function, not requiring any argument. However, you can achieve that, by making the callback function anonymous, and call any function from it. In this way, you can pass variables.
PS : Let me know if I got it wrong in any manner :)
Let's assume that you will be passing it to a pure JS function.
function myFunc() {
console.log("My function!");
}
In your 'click', you're calling the function ''resalter'', that you're also defining on the spot.
You want to call myFunc, so:
$(clase).on('click', myFunc())
Now, myFunc is not expecting a variable. Let's just pass a variable:
function myFunc(myVar) {
console.log("Passing a variable of type: " + typeof myVar);
}
Now, you're only expected to pass this var in the function you're calling. Given the previous example I gave, we have:
let x = 1; // our variable
$(clase).on('click', myFunc(x))
This way you're passing 'x' as a variable, of type integer. Use this code as inspiration to try and reach your goal. It is a bit hard to give a more exact answer, given that we don't know what variables have to be passed to what function and what the purpose is.
Good luck!

Cannot update global variable within addeventListener function

Basically when running addEventListener I cannot access any of my saved variables from outside the function I am creating.
In the following code I always get the error Property 'xAxisLabel' does not exist on type 'HTMLElement'.
xAxisLabel:string = 'xAxis';
xAxisField:HTMLElement;
filterChanged(element: HTMLElement) {
element.addEventListener("change", function(){
this.xAxisLabel = 'Countries';
});
}
ngOnInit() {
this.xAxisField=document.getElementById('xAxisField');
this.filterChanged(this.xAxisField);
}
I am sure it's a fairly simple solution but I haven't been able to find it online. Any help would be appreciated.
It is due to 'this' keyword binding. You need to change your code to use arrow function, so:
filterChanged(element: HTMLElement) {
element.addEventListener("change", () => {
this.xAxisLabel = 'Countries';
});
}
now this.xAxisLabel refers to correct value

Polymer properties from chrome console

This is a very newbie question, but how can I reference a polymer property from Chrome's console? I know I can output (console.log) from javascript in my application with a reference to this.myProperty, but how do I get a reference to it straight from the console?
You get a reference to the element by some method, I use querySelector so if you have a paper-input with the class username-input you can do something like this
document.querySelector('paper-input.username-input').myProperty
and that would be the same as doing a this.myProperty from inside the element.
During development only I create a property on window that references my
element.
Polymer({
is: 'nav-bar',
properties: {
foo: {
type: String,
value: 'foo'
}
},
attached: function() {
// #TODO remove before merge.
window.navBar = this
}
})
And in your console:
// log property
navBar.foo
// call methods
navbar.doSomething()
to check properties or call methods on my element.
Granted, this pollutes the global scope but I do this only during development.
You can also select the element via querySelector('nav-bar') but it's tedious
to do so and you lose console autocompletion. Time is money.

Observing an array that is initialised in the created lifecycle event

I have a working Polymer prototype, a code snippet of which is:
Polymer({
myData: [],
observe:{
myData: 'myDataChange'
},
myDataChange: function(val, newVal){ ... }
...
However, under the the attribute hinting section of the developer API, it states that objects and arrays should be initialised in the created lifecycle callback, not on the prototype. So, I changed the code snippet above to:
Polymer({
created: function(){
this.myData = [];
},
observe:{
myData: 'myDataChange'
},
myDataChange: function(val, newVal){ ... }
...
As soon as I make this change, the change watcher function no long invokes.
The myData property of my element instance is being populated by jQuery in an document ready callback. Moving this code into a 'polymer-ready' callback on the containing page solves this issue.
My concern with this is that my pages are going to be littered with polymer-ready events for the initial data population.
I amended my prototype so that the custom element is added to the DOM after a 5 second timeout, after the polymer-ready event was fired. Injecting the DOM like this doesn't fire the polymer ready event again.
Is this the correct/best approach to initialising properties on a Polymer element? I could manually fire an event from my custom element to say its loaded but this seems a bit crude. Any better ideas?
You shouldn't use any custom element before polymer-ready event (unless you're doing it intentionally), I think the best you could do is to replace every ready callback with polymer-ready.
However if you still want to use ready callback you could call myDataChange inside the element's ready callback:
Polymer({
created: function(){
this.myData = [];
},
observe:{
myData: 'myDataChange'
},
ready: function() {
this.myDataChange([], this.myData);
},
myDataChange: function(val, newVal){ ... }
....

Angular Directive: How to check if a scope function is defined?

I know you can have optional property using a question mark like x:"=?" and then you can check if it is specified by checking if x is undefined or null.
How can I do similar thing for a function? Oftentimes, I want to hide a control if the function is not specified. I have to define another property for this purpose to workaround this problem. I wonder if there is a way to save this extra property.
I found an answer to this question at here. Here is a recap in case somebody is interested:
In directive:
scope: {
callback: '&'
},
link: function(scope, elem, attrs) {
scope.hasCallback = function() {
return angular.isDefined(attrs.callback);
}
}
In html:
Call me back
I like it very much because it saves me an extra parameter.