Data-binding function parameter within ngFor - javascript

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 ....

Related

Passing object as a parameter in a template literal in 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.

Code doesn't work after combining two statements

This is original code:
h1tag= document.getElementById("myHeading");
h1tag.addEventListener("mouseover", ()=>{h1tag.style.backgroundColor="blue"});
After combining:
h1tag= document.getElementById("myHeading").addEventListener("mouseover", ()=>{h1tag.style.backgroundColor="blue"});
What is the reason behind this?
The problem with this line :
h1tag= document.getElementById("myHeading").addEventListener("mouseover", ()=>{h1tag.style.backgroundColor="blue"});
Is that the statement is evaluated from left to right, so the last method that will be called is addEventListener, so in other words you are trying to store the returned result from addEventListener in your h1tag variable while addEventListener doesn't have a return type so it will return undefined.
To expand on the previous answers, the key issue here is that h1tag is not defined (because addEventListener doesn't return a value) and you are trying to change it's properties.
Fortunately, javascript provides a way to access the element that an event is called on, through an argument passed to the event function.
Try running
document.getElementsById("myHeading")
.addEventListener("mouseover", (e)=>{e.target.style.backgroundColor = "blue"})
h1tag is not defined in your second attempt.
document.getElementById("myHeading").addEventListener("mouseover", (e)=>{e.currentTarget.style.backgroundColor="blue"});
if you still want to kep a reference to the element:
(h1tag=document.getElementById("myHeading")).addEventListener("mouseover", (e)=>{e.currentTarget.style.backgroundColor="blue"});

Javascript functions embedded in arguments run automatically?

I am investigating defending against various types of attacks and I've found one I don't quite understand.
I have the following html:
<body onload="foo(''/alert(/Gotcha/)/'');">
<script>
function foo(){
alert("Inside Foo");
}
</script>
</body>
</html>
If you run this, you'll see an alert that says "/Gotcha/" followed immediately by one that says "Inside Foo".
What's going on? Why is the alert in the argument (that foo doesn't even have) running?
What's more, if I remove any of those slashes or single-quotes in the argument, it doesn't work.
if I change it to
<body onload="foo('/alert(/Gotcha/)/');">
All I get is "Inside Foo".
if I change it to
<body onload="foo('/alert(Gotcha)/');">
or remove any of the /s I don't get anything.
What is it about the ' and the / that makes this work?
We have a complicated expression there so let's break it up:
foo(''/alert(/Gotcha/)/'');
JS interprets this as a call to a function foo with ''/alert(/Gotcha/)/'' as a parameter (functions in JS do not have hard params, you can send as many as you'd like, even if the function declaration does not specify them)
The parameter is evaluated as the string '' followed by the division character /, followed by the alert function, then another division and another empty string
The parameter for the alert is evaluated since it's not a string, but a regular expression and the string representation is, incidentally, the same as the input regular expression string
The alert is executed with the string representation of the regex to evaluate the parameter for foo and the result of the whole parameter expression is NaN because the strings aren't divisible which doesn't really matter since the function foo does not use it
The function foo is executed.
The reason the argument in the foo call runs is because it is being interpreted as JavaScript. The arguments you are passing in foo(''/alert(/Gotcha/)/'' is essentially 2 strings and in the middle of them is a alert call.
Function arguments are all evaluated before the function is called. So when you write:
foo(alert('/Gotcha/'));
it first evaluates alert('/Gotcha/'), which causes /Gotcha/ to be displayed. Then the return value of alert() is passed as a parameter to foo(). foo() ignores its parameter, but that doesn't matter for the first step.
When you change it to
foo('/alert(/Gotcha/)/');
then the argument is a literal string, not a function call. So evaluating it just returns the string contents, it doesn't call the alert() function.
I can't see any reason why
<body onload="foo('/alert(Gotcha)/');">
would behave any differently from
<body onload="foo('/alert(/Gotcha/)/');">
so I suspect that your actual code has a typo that you didn't copy here. Check your Javascript console for syntax error messages.
Q: "Javascript functions embedded in arguments run automatically?"
A: It has nothing to do with function arguments. The foo function is there to simply add to the confusion of an already obfuscated expression. This is a simply a complicated way of writing an equivalent of:
onload="alert(/Gotcha/)"
which wants to alert the content of /Gotcha/ regex literal.
The regex literal provided in the string of the body onload assignment is simply the passive value of the alert function provided in that same string and has no share in what's going on there.
Everything else is simply a clever way of masking a simple assignment such as the above given onload="alert(/Gotcha/)" line of code.
The only thing that makes it work is the fact that inline event assignments are strings that need to get evaluated in order to get executed.
Therefore eval( ''/alert(/Gotcha/)/'' ) will do the same. Or putting it all back in its original form: eval( "foo(''/alert(/Gotcha/)/'');" ).
So yes, it is possible to execute any kind of string content assigned inline to an element event. But then, so is the setTimeout("foo(''/alert(/Gotcha/)/'');", 1000) capable of doing exactly the same.
So, "no" it has nothing to do with function arguments, but with the parsing of string content to the inline event of document body element.
EDIT:
Inline JavaScript on strings containing html for Images is (for the reasons explained above on why that Gotcha alert works) the most dangerous code injection without the need of user input. That's because image elements can handle onerror events, to which any arbitrary block of code can be executed, as in:
<img
src="http://Idontexist.com/wrongfolder/missingimage.jpg"
onerror="your arbitrary, but well written (malicious) code here!"
>

Why can't I pass an angular variable as a function parameter?

I'm trying to pass the follower through the followPerson() function. This works fine if I do followPerson(123). But when I do followPerson({{follower.follower}}) it doesn't fire.
{{follower.follower}} definitely works as it's shown in bold.
<div ng-repeat="follower in followers.followers">
<b>{{follower.follower}}</b>
<a ng-click="followPerson({{follower.follower}})">Follow</a>
</div>
You must not use interpolation ({{) for the arguments in the ng-click handler, it will just result in a parse error (If not using very old angular versions) due to invalid expression. You just need to pass the argument expression as is, angular will just evaluate is against the scope while evaluating the ng-click handler.
Just do:
ng-click="followPerson(follower.follower)"
Have a look at your console for errors.

ASP.NET Calling defined JS-function with RegisterStartupScript

In ASP.NET we are calling defined js-functions with the:
Page.ClientScript.RegisterStartupScript(GetType(), "", "JSFuncNameHere();", true);
I wonder:
Why there isn't any method, which has a name like: Page.ClientScript.CallJSScript("someJSFunc");
Why does the upper-method require the reflection method GetType() ? Something isn't defined at runtime, is it?
Why do I need the 2nd argument key? As I have tested, I can left it empty and the existed JS-function shall be called.
Why there isn't any method, which has a name like: Page.ClientScript.CallJSScript("someJSFunc");
Probably because this is more generic solution, since by just adding 2 characters you get the same result and if you need you can add arguments and anything else.
Why does the upper-method require the reflection method GetType() ? Something isn't defined at runtime, is it?
Why do I need the 2nd argument key? As I have tested, I can left it empty and the existed JS-function shall be called.
For both of these the same reason - the method will detect if you run the same script multiple times and in such case, call it just once. The two arguments are the means how it identifies duplicates - a key is not sufficient since another class in a different library might be using the same key - so you need to pass in the type of your own class to ensure that the script is executed when you want it to.

Categories

Resources