3

I am trying to call a function from my ViewModel from a click event. It appears that the function goes out of scope the moment I call it from within a foreach loop. New to JavaScript, and trying to wrap my head around how / why has proved futile.

Function:

$dyn.controls.Test = function (props, element) {
    var self = this;

    $dyn.ui.Control.apply(this, arguments);
    $dyn.ui.applyDefaults(this, props, $dyn.ui.defaults.Test);

    self.RowItem = [
        {
        .
        .
        .
        }];

    self.Periods = [
        { Label: "13:00", Open: true },
        { Label: "13:10", Open: true },
        .
        .
        .
        { Label: "14:30", Open: true }];

    self.clickedMe = function (action) { //This is the function I want to call
        alert("Clicked");
    };
    .
    .
    .

In HTML, this works:

<div data-dyn-bind="foreach: $data.RowItem" class="table" id="workspace">
    <div class="row">
        <div class="resourceCell" data-dyn-bind="attr: {id: $data.Id}">
            <div data-dyn-bind="text: $data.Id" class="resourceCell_inner"></div>
        </div>
        <div class="periodRow" data-dyn-bind="foreach: $parent(0).Periods, click: function(event) {$parent(0).clickedMe(event);}">
            <div class="periodCell"></div>
        </div>
    </div>
</div>

and this does not:

<div data-dyn-bind="foreach: $data.RowItem" class="table" id="workspace">
    <div class="row">
        <div class="resourceCell" data-dyn-bind="attr: {id: $data.Id}">
            <div data-dyn-bind="text: $data.Id" class="resourceCell_inner"></div>
        </div>
        <div class="periodRow" data-dyn-bind="foreach: $parent(0).Periods">
            <div class="periodCell" data-dyn-bind="click: function(event) {$parent(0).clickedMe(event);}"></div>
        </div>
    </div>
</div>

However, I obviously want my function to be called from the "cell" divs, not the row. Any advice?

0

2 Answers 2

2

Once you're in the scope of another foreach loop, the $parent keyword no longer refers to the object you think it is ($root) but to the Periods array.

Whenever you know that the function / property you're referring to is on the root view-model, you should use $root instead:

<div class="periodCell"
     data-dyn-bind="click: function(event) { $root.clickedMe(event); }"></div>
5
  • I tried this before (And now again) but $root still does not give me access to the function. Commented Mar 15, 2016 at 10:27
  • @Weezul-HiGHSoftware Is there any error in the console?
    – haim770
    Commented Mar 15, 2016 at 10:28
  • Yeah, same error: "TypeError: Object doesn't support property or method 'clickedMe' at click (Function code:17:48)" I must add, I am trying this in Dynamics AX, and am starting to suspect that Microsoft's implementation might be slightly different to what it is supposed to, as I believe your suggestion to be the right answer (Will mark it as such also) However, I get no error on $root, and cannot imagine that they would not use the standard libraries. Commented Mar 15, 2016 at 10:40
  • @Weezul-HiGHSoftware Maybe you need to use the same syntax that AX uses for parent. Try with $root(0) instead. If it still doesn't work, you can also try $parent(0).$parent (although not recommended).
    – haim770
    Commented Mar 15, 2016 at 10:43
  • I have tried both of those before, get the error that it is expecting a function the moment I add brackets to $root, or the same message as above when using parent.parent. I also looked through existing code in other places where they use the same with no luck. Thanks for the help anyway, will continue searching through their code :) Commented Mar 15, 2016 at 10:50
1

First one works because scope is same, but in a loop, every iteration is represented as $data and this might not have the property clickedMe. You can try using

$parent.$parent(0).clickedMe(event);

Here $parent will point to the initial scope and from there you can go to its parent using $parent(0).

Also, instead of

click: function(event) {$parent(0).clickedMe(event);}

you can try

click: $parent(0).clickedMe

event is automatically added as parameter.

Not the answer you're looking for? Browse other questions tagged or ask your own question.