Skip to content

Object property with the same name as a local variable in template throws when handling events #7759

@rpdasilva

Description

@rpdasilva

Repeating over a set of objects in a template throws a TypeError when attempting to call a method with the same name as a local variable. In this case looping over a list of "action" objects and dynamically generate buttons i.e.

Edit: More concise example: https://plnkr.co/edit/QAygbyXHgseecK3xKTm9?p=preview

<div #action>
   <!-- ... some markup ... -->
   <div class="nested">
      <button *ngFor="#thing of things"
        (click)="thing.action($event)">
        {{thing.label}}
      </button>
  </div>
  <!-- ... some more markup ... -->
</div>

Original example: https://plnkr.co/edit/qIIz03Zq6R8iEGeCgP5N?p=preview

<button *ngFor="#action of actions"
    (click)="action.action($event)">{{action.label}}</button>

Angular 2: 2.0.0-beta.12
OS X: 10.11.2
Chrome: 49.0.2623.87 (64-bit)

TypeError: l_action2_0 is not a function
    at AbstractChangeDetector.ChangeDetector_Comp_2.handleEventInternal (VM1171 viewFactory_Comp:355)
    at AbstractChangeDetector.handleEvent (VM1197 angular2.dev.js:9833)
    at AppView.triggerEventHandlers (VM1197 angular2.dev.js:10511)
    at eval (VM1750 viewFactory_Comp:579)
    at VM1197 angular2.dev.js:13979
    at VM1197 angular2.dev.js:13407
    at ZoneDelegate.invoke (VM1180 angular2-polyfills.js:332)
    at Object.NgZoneImpl.inner.inner.fork.onInvoke (VM1197 angular2.dev.js:2216)
    at ZoneDelegate.invoke (VM1180 angular2-polyfills.js:331)
    at Zone.runGuarded (VM1180 angular2-polyfills.js:241)

Looking at the transpiled code, it seems the issue appears to be in CodeGenViewFactory trying to reference the action.action()method as if it were the local variable action

l_action0_0 = locals.get('action'); // <- this is going to get your action object, {label: 'Method, action: Function}
l_event1_0 = locals.get('$event');  // <- this gets the event that is going to be sent to your function, this case MouseClick
l_action2_0 = locals.get('action'); // <- here is the problem, I think since action is the local template
                                    //    variable name the code gen generates a locals.get instead of function
                                    //    invocation, because the property has the same name and it gets lost
                                    //    (should be smart to see that is a invocation from the template local variable
                                    //    and not apply locals to get from ngFor context)

Changing the local variable name allows this case to work as expected

l_actionObj0_0 = locals.get('actionObj');
l_event1_0 = locals.get('$event');
l_action2_0 = l_actionObj0_0.action(l_event1_0);  // <- looks good right because my local template variable is #actionObj

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions