Passing object as a parameter in a template literal in javascript - javascript

I currently have an object which I want to pass as a parameter to another function inside a template literal:
var template = `<button onclick="onclick(${object})"></button>`;
However, this makes the parameter become a string value: [object Object] and doesn't pass the parameter. Is there any way to pass this parameter into the function?
Thank you very much in advance.

You are going to need to represent your object as a string. You can do this using JSON.stringify:
var template = `<button onclick="handleClick(${JSON.stringify(obj).split('"').join(""")})"></button>`;
You will need to escape double quotes (which this code does), and single quotes if used for your onclick event (this code doesn't).
onclick="onclick" actually calls window.onclick - meaning that it picks up clicks anywhere. You should use a different name (such as handleClick).
I would suggest refraining from using inline event listeners for reasons like this, and because they can cause issues if you ever need to adopt a content-security-policy.

Related

Thymeleaf passing fragment parameter to javascript method with th:onclick

I'm trying to use th:onclick to call a submit() on form whose ID is given as Thymeleaf variable. I write:
th:fragment="fragGname(formname)"
......
th:onclick="'document.getElementById(\'' + ${formname} + '\').submit();'">
But I receive the error
org.thymeleaf.exceptions.TemplateProcessingException: Only variable expressions returning numbers or booleans are allowed in this context, any other datatypes are not trusted in the context of this expression, including Strings or any other object that could be rendered as a text literal. A typical case is HTML attributes for event handlers (e.g. "onload"), in which textual data from variables should better be output to "data-*" attributes and then read from the event handler.
Where is the mistake? Thanks!
I got it:
th:onclick="document.getElementById([[${formname}]]).submit();"

Data-binding function parameter within ngFor

I'm trying to bind the value of cat to the (click) function parameter and understandably getting an error. Is there a way I can do this without looping a parent element of the <button>?
<button type="button" (click)="UpdateCategoryFilter({{cat}})" *ngFor="let cat of categories">
{{cat}}
</button>
Never combine [...] or (...) with {{...}} either one or the other, but not both at the same time
It should be
(click)="UpdateCategoryFilter(cat)"
{{...}} is also only for string interpolation. Values bound this way will always be strings, while [foo]="someValue" will pass someValue with the original type if foo is a property.
In html, the code you write in between the quotation marks of an event (such as (click)) is a pure typescript/js code, and as you would not write {{cat}} in your typescript code, you shouldn't write it in the place you wrote it.
Imagine that what you just tried to do is replacing the cat with it's code value, and then executing the code UpdateCatagoryFilter(x), where x is cat's value, and you try to use it as a variable name.
The meaning of (event)="..." syntax is: when an event event is emitted, execute the code ....

AngularJS invoking function whose name is constructed as a string

I have a situation in which there are main functions named as:
Add_<Element_Type>_Page()
where Element_Type is received as a parameter.
I can see two options to handle the invocation of the correct function:
Write a relatively long switch construct covering all possible values of Element_Type, or
Use some existing mechanism/trick (I'm not aware of) through which I can build a string using the received Element_Type and invoke a function whose name is contained in that string.
Needless to say, all the functions that can be invoked this way have exactly the same signature as far as parameters is concerned.
Obviously, Option 2 would be the best (easy to maintain and very general as no changes are needed whenever a new type of pages is added).
Is this possible to achieve within AngularJS framework?
Thanks in advance.
You can simply do that using the [...] notation instead of .
Like this,
$scope["Add_" + Element_Type + "_Page"]()
will call $scope.Add_test_Page() assuming Element_Type would be test
or if using controllerAs syntax,
vm["Add_" + Element_Type + "_Page"]()
where Element_Type is a received parameter as you mentioned.
If you want to use it inside HTML, you can have a reference to your Element_Type in $scope/vm (whichever way you are using) and access it.
Create an attribute with name func-name and pass your dynamic string value which is your function name to that attribute and within your directive you can do something like this.
scope: {
funcName: '#'
},
controller: function() {
$scope[$scope.funcName]();
}

Object has no method 'apply'

I am creating a few DOM elements dynamically like,
var anchorElement = jQuery('<a />',{text:property.text});
var liElement = jQuery('<li />',{"class":"navlink_"+i,id:"navlink_"+i});
anchorElement.on('click',property.fnctn);
liElement.append(anchorElement);
parentID.append(liElement);
Where property is a JSON object.
property.text is the text that I want to put into anchor element. (Works fine)
I want to attach a click event handler to that anchor element.
The function that needs to be bound to that element is specified in JSON and we can access it like
property.fnctn
The following line should bind the event handler to the anchor element.
anchorElement.on('click',property.fnctn);
This was not working so I tried converting it into string like,
anchorElement.on('click',property.fnctn.toString());
No Success...
When I click on this link, the error is logged in the console
The object has no method 'apply'.
What is the reason...???
I am able to get it working with a slight work around like
anchorElement.attr('onclick',property.fnctn+"()");
Above statement works, but I want to know why .on() API is not working.
Thanks :)
AÐitya.
Update:
Youve said that property.actfn is a string, "paySomeoneClick". It's best not to use strings for event handlers, use functions instead. If you want the function paySomeoneClick, defined in the string, to be called, and if that function is global, you can do this:
anchorElement.on('click',function(event) {
return window[property.fnctn](event);
});
That works because global functions are properties of the global object, which is available via window on browsers, and because of the bracketed notation described below.
If the function is on an object you have a reference to, then:
anchorElement.on('click',function(event) {
return theObject[property.fnctn](event);
});
That works because in JavaScript, you can access properties of objects in two ways: Dotted notation with a literal property name (foo.bar accesses the bar propety on foo) and bracketed notation with a string property name (foo["bar"]). They're equivalent, except of course in the bracketed notation, the string can be the result of an expression, including coming from a property value like property.fnctn.
But I would recommend stepping back and refactoring a bit so you're not passing function names around in strings. Sometimes it's the right answer, but in my experience, not often. :-)
Original answer:
(This assumed that property.fnctn was a function, not a string. But may be of some use to someone...)
The code
anchorElement.on('click',property.fnctn);
will attach the function to the event, but during the call to the function, this will refer to the DOM element, not to your property object.
To get around that, use jQuery's $.proxy:
anchorElement.on('click',$.proxy(property.fnctn, property));
...or ES5's Function#bind:
anchorElement.on('click',property.fnctn.bind(property));
...or a closure:
anchorElement.on('click',function(event) {
return property.fnctn(event);
});
More reading (on my blog):
Mythical methods
You must remember this
Closures are not complicated

How to convert a javascript string to a javascript function, preserving the correct "this"?

A browser element has an onpopupshowing attribute, which is a string consisting of several javascript statements.
I want to "override" that bit of javascript.
Were this a function, I'd just assign it to a variable, assign my "overriding" function to the element attribute, and (if need be) call the original function from my overriding one, pretty much like this:
var oldfunc;
function myoverrridingfunc () { my statement; oldfunc(); my other statement; }
oldfunc = element.getAttribute( "onpopupshowing" )
element.setAttribute( "onpopupshowing", myoverrridingfunc );
but element.getAttribute( "onpopupshowing" ) isn't a function, it's a string.
I could use the Function object to turn the string into a function, but the string includes references to this. How do I preserve the right this?
What's the best way of intercepting/overriding this bit of script? Note: this only needs to work in Firefox, not in any version of java/ECMAscript.
Thanks.
var oldfuncStr = element.getAttribute("onpopupshowing");
element.removeAttribute("onpopupshowing");
var oldfunc = new Function(oldfuncStr);
element.addEventListener("popupshowing", function()
{
myStatement;
oldfunc.call(this);
otherStatement;
}, false);
call is specifically for specifying this. I tested in Firefox, but with onclick event rather than onpopupshowing.
Perhaps you are overthinking this. Why not just wrap your JavaScript statements in quotes and assign it to the attribute? If the attribute expects JavaScript statements as a string, I wouldn't expect that assigning a function reference would even work anyway. (does it?)

Categories

Resources