-1

I'm trying to bind inputs from the back side to the front and got a question: to avoid crazy parsing exercise, can I use an income variable as a condition for *ngIf instruction? Like this:

    <div *ngFor="let ban of banners">
        <div *ngIf="ban.view_condition">
            <a [href]="ban.url" target="_blank">
                <img [src]="ban.img_url" [alt]="ban.title">
            </a>
        </div>
    </div>

In ban.view_condition I'm trying to pass something like: "(parameterN == true || size > 5)"

So the idea is to pass from the backend the set of properties that I want to check and based on this result - display or not the banner. Main goal - avoid manual validation.

Example: (that's what I reveive from back) ban.view_condition = "app.size==10||userName=='test'";

Basically I want to take the value and get something like: *ngIf="app.size==10||userName=='test'" in the end.

Is it feasible? Of course, I understand that all targeted properties need to be present in the component. Thanks for any inputs or ideas!

mhodges
  • 10,938
  • 2
  • 28
  • 46
Eugene
  • 301
  • 2
  • 12
  • What exactly would be the question here? This is one of the main use case for the `*ngIf` directive. To render elements conditionally. – ruth Feb 22 '21 at 21:33
  • yeah, but it doesn't work like this :( – Eugene Feb 22 '21 at 21:34
  • it just checks if the value is present, but not the value itself – Eugene Feb 22 '21 at 21:34
  • @Eugen Well, saying `*ngIf="..."` is the same as saying `if(...)`, it will accept an expression and evaluate it for truthyness. If you want to check the value for something other than truthyness, you need to do that manually. i.e. `*ngIf="ban.view_condition === 'show'"` etc. – mhodges Feb 22 '21 at 21:36
  • yes, I understand. My idea is to pass the exprection (conditional) to the ngIf with the variable from the backend. So ban.view_condition will have the expression for evaluation – Eugene Feb 22 '21 at 21:37
  • @Eugen Ah, then you need to evaluate it manually. I'd suggest creating a function to do that – mhodges Feb 22 '21 at 21:38
  • my actual idea was to avoid that :D – Eugene Feb 22 '21 at 21:40
  • @Eugen Can you give a more concrete example with your component and an example of a condition you want to check for? I think that determines what you will be able to do or not do. In other words, a complete minimal example to reproduce the problem you are having – mhodges Feb 22 '21 at 21:42
  • yes, please see the question, I've updated with example – Eugene Feb 22 '21 at 21:45
  • What is `app.size` and `userName` in your example? Are those properties of your component? calling a function that uses `eval(conditions)` seems to be the correct solution here based on what you want, but suggesting that kind of makes me cringe. It's a huge security liability and you have to be sure that everything is in scope – mhodges Feb 22 '21 at 21:47
  • in this case, inside of the method (in the component), I will have to split the input string, take each input property + it's value and compare with existing values in the component and return true/false. My plan is to put required parameters (there are 3 values actually) in the component as public and avoid using methods to compute if it's true/false. You see the idea? – Eugene Feb 22 '21 at 21:49
  • "avoid using methods to compute if it's true/false" This is not possible. The only way to manually evaluate a string as JS code is to use the `eval()` function, which is not available inline in the `*ngIf="..."` directive – mhodges Feb 22 '21 at 21:56
  • thanks for your comments! – Eugene Feb 22 '21 at 21:59

2 Answers2

2

I would recommend creating a function in the controller that determines whether the banner should be displayed.

However, if you still want to evaluate that string as actual code. You may use the eval function.

evaluate(condition: string) {
    // eval(condition) will evaluate javascript code and execute it.
    return eval(condition);
}

Also, you must ensure any properties in the condition actually exist. (valid javascript)

I would still argue this is not the best approach, and you should reconsider your design.

JhonRM
  • 203
  • 3
  • 10
  • I def agree with @JhonRayo99 this is the best option you have, better you better change your design. – Nadhir Falta Feb 22 '21 at 21:56
  • FYI this is a huge security liability and should not be used unless you are absolutely sure of what you're doing. – mhodges Feb 22 '21 at 21:57
  • 1
    @Eugene, if you are retrieving the condition from the backend, why don't you simply return a boolean value? – JhonRM Feb 22 '21 at 22:00
  • 2
    @Eugene: Binding a function to a directive with default change detection strategy would cause the function to be invoked for each CD cycle. This might be negligible for smaller functions but would quickly lead to a performance overhead. This also doesn't look like clean design. You're creating a tight coupling b/n backend and frontend by using same variable names. Ideally the backend should evaluate the condition and should only return the resulting boolean – ruth Feb 22 '21 at 22:03
  • 1
    @MichaelD 100% agreed - this is not a solution, it's a hack to cover up bad code design. Classic case of an ["XY problem"](https://meta.stackexchange.com/a/66378) – mhodges Feb 22 '21 at 22:07
  • @MichaelD I totally agree with you, but the person who is doing backend doesn't want to do the change... – Eugene Feb 22 '21 at 22:21
0

You can just call a method and evaluate dependening on your current ban item what the result should be.

<div *ngFor="let ban of banners">
        <div *ngIf="calculateShow(ban)">
            <a [href]="ban.url" target="_blank">
                <img [src]="ban.img_url" [alt]="ban.title">
            </a>
        </div>
    </div>

public calculateShow(ban: any){
//call backend
//decide if you wish to return true or false here
}

Basically I want to take the value and get something like: *ngIf="app.size==10||userName=='test'" in the end.

Yes it is absolutely feasible, considering that app.size and username exist as fields on your .ts file

Panagiotis Bougioukos
  • 15,955
  • 2
  • 30
  • 47
  • in this case I need to parse all data from ban and make a descision. My wish is to delegate descision to the page based on the variable value (see the question, I've updated) – Eugene Feb 22 '21 at 21:45
  • in case if I pass from the backend : ban.view_condition = "hasValue()", I expect *ngIf to call this method in my component. If this method is not present , it should return an exception. With simple *ngIf="ban.view_condition" - it doesn't refer to the actual value of the income variable, only check if it's not null (probably) or present – Eugene Feb 22 '21 at 21:51