NativeScript icon indicating copy to clipboard operation
NativeScript copied to clipboard

Can not use nested object method in expression for binding

Open webleaf opened this issue 7 years ago • 6 comments

Environment

  • CLI: 5.0.1
  • Cross-platform modules: 5.0.5
  • Android Runtime: 5.0.0
  • iOS Runtime: not installed

To Reproduce

class ViewModel extends Observable {
    public obj = {
        fun: function () {
            return "It's fun()"
        }
    }
}

const vm = new ViewModel();
<Label text="{{ obj.fun() }}"/>
Binding: Run-time error occured in file: undefined at line: undefined and column: undefined

Same result if it used, as ListView item bindingContext.


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

webleaf avatar Dec 19 '18 12:12 webleaf

@webleaf NativeScript Core is supporting nested objects but is not supporting calling methods. Still, in the common case, you could write your Observable view model to work with properties and update the values you need to receive in the code-behind.

For example this Playground demo - instead of calling the method fun() directly from the XML just call it to update the message value

export class HomeViewModel extends Observable {
    private _message: string;

    constructor() {
        super();

        // call this.fun() when needed to update the message property
        this.fun();
    }

    fun() {
        this.message = "This is so much Fun!";
    }

    get message(): string {
        return this._message;
    }

    set message(value: string) {
        if (this._message !== value) {
            this._message = value;
            this.notifyPropertyChange("message", value)
        }
    }
}

As a side note NativeScript, do supports nested objects but they need to be created as an observables. For example:

vm.set("moreFun", fromObjectRecursive({ obj: {fun: "more fun!"}}))

which can be used as follow:

<Label textWrap="true" text="{{ moreFun.obj.fun }}" class="h2 description-label" />

NickIliev avatar Dec 19 '18 13:12 NickIliev

@NickIliev in your example of HomeViewModel method fun() can be called. It works. And it's documented (Supported expressions) Then calling nested methods could be Feature Request.

webleaf avatar Dec 19 '18 14:12 webleaf

I find workaround.

class ViewModel extends Observable {
    public obj = {
        fun: function () {
            return "It's fun()"
        }
    };

    public call(fun: Function, thisArg, ...args) {
        return fun.call(thisArg, ...args);
    }
}
<Label text="{{ call(obj.fun, obj) }}"/>

It works. But still it would be nice if this feature supported without such workaround.

webleaf avatar Dec 19 '18 14:12 webleaf

@webleaf you are right - marking this one as a feature request.

NickIliev avatar Dec 19 '18 14:12 NickIliev

can I take this issue ,please.I need a merged PR for my university assignment.

nadasuhailAyesh12 avatar Mar 18 '24 09:03 nadasuhailAyesh12

You absolutely can @nadasuhailAyesh12 - feel free to post a PR referencing the issue if you would like to try it.

NathanWalker avatar Mar 18 '24 16:03 NathanWalker