0

I have an root-app component which is defined like this in the template.

template: `
<dev-table (complete)="onSelect(developer)"></dev-table>
<dev-details [selectedDeveloper]="selectedDeveloper"></dev-details>
`
directives: [DevDetailsComponent, DevTableComponent],
providers: [DevValueService, provide(DevService, {useClass: DevService})]

is a list and on selection of one of the internal list it should send the value of the list (developer) which is passed into as selected developer. @Input is defined right and is taken into correctly. But the @output is giving an error Error: Output is not defined What definition is needed or what is the definition method. I am missing something.

This is the class definition:

@Component({
  selector: 'dev-table',
  template: `
    <ul class="dev">
      <li *ngFor="#developer of developers"
        [class.selected]="developer === selectedDeveloper;this.complete.next();"
        (click)="onSelect(developer)">
        <span class="spanbackground">{{developer.name}}</span> -  {{developer.skill}}
      </li>
    </ul>  
  `, 
  providers: [DevService]
})

export class DevTableComponent implements OnInit{
    public developers : Developer[];
    public selectedDeveloper : Developer;
    constructor(private _DevService: DevService) { }
    @Output() complete = new EventEmitter(); 
    public onSelect(developer: Developer) { this.selectedDeveloper = developer; }
    getDevelopers(){
      this._DevService.getDevelopers().then(developers => this.developers = developers)
    }
    ngOnInit(){
      this.getDevelopers();
    }
}

UPDATED: The final working code did not have developer === selectedDeveloper;this.complete.next(); rather this.complete.next() was put into the onSelect function.

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
Gary
  • 2,293
  • 2
  • 25
  • 47
  • 2
    Did you add this? `import {Output} from "angular2/core";` – Langley Jan 15 '16 at 09:39
  • Thank you. I did that and am getting `Binding expression cannot contain chained expression at column 33 in [developer === selectedDeveloper;this.complete.next();] in DevTableComponent@3:8 ` . What I am technically doing is passing the value of developer to parent component. and then passing it as input to .dev-details is working correctly isolated. But unable to capture the event sent with value. – Gary Jan 15 '16 at 09:42
  • 1
    You can't add that much code into the template, you must add all that logic into a function that returns a boolean and call it like this: `[class.selected]="shouldSelect()"` – Langley Jan 15 '16 at 09:44
  • Okay Thanks. Do I also have to import `EventEmitter`? Getting undefined error. Isnt that part of the component. – Gary Jan 15 '16 at 09:50
  • 1
    Yea. Any class you are using you have to import it. OnInit, Developer, DevService ... – Langley Jan 15 '16 at 09:50
  • Thanks that resolved. I am not getting the selected value from internal list however. I am also doing `this.complete.emit(someValue);` – Gary Jan 15 '16 at 09:56
  • 1
    try `onSelect($event)` ? – Langley Jan 15 '16 at 10:02

2 Answers2

2

If you want to pass the value to the parent component you can leverage custom event. This code is located in the template of the parent component:

@Component({
  (...)
  template: `
    <dev-table (complete)="someMethod($event.value)"></dev-table>
  `
})
export class ParentComponent {
  someMethod(value) {
    console.log('complete event - value = ' + value);
  }
}

To trigger the event, you could do something like that in your child component:

@Component({
  (...)
  template: `
    (...)
    <span (click)="triggerCompleteEvent()">Trigger complete event</span>
  `
})
export class DevTableComponent implements OnInit{
  @Output()
  complete:EventEmitter;

  constructor() {
    this.complete = new EventEmitter();
  }

  triggerCompleteEvent() {
    this.complete.emit(someValue);
  }
}

someValue corresponds to the value you want the event contains and event subscribes can get.

Hope it helps you, Thierry

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Is this function complete supposed to be in the parent directive or the actual directive. $event.value is some value in my list within the directive. – Gary Jan 15 '16 at 09:52
  • Value captured and event is triggered right. But the parent is coming undefined. `
    • {{developer.name}} - {{developer.skill}}
    ` and class has `onSelect(developer: Developer) { this.selectedDeveloper = developer;console.log(this.selectedDeveloper);this.complete.emit(this.selectedDeveloper); } ` . In parent ``
    – Gary Jan 15 '16 at 10:47
  • Safely passing the data now. Thanks. – Gary Jan 15 '16 at 12:31
2

"@output is giving an error Error: Output is not defined What definition is needed or what is the definition method. I am missing something." :

import {Output} from "angular2/core";

You have to import the definition of any class you are using.

Langley
  • 5,326
  • 2
  • 26
  • 42
  • All worked and the code is working now. I have defined the event within the child directive. The data is captured on click (console.log works fine). I am able to pass events correctly from within the directive - no errors generated. using `this.complete.emit(someValue);` but I am not able to capture the event in the parent component `` It gives $event.value as undefined in parent. Is there a capture process that is different? – Gary Jan 15 '16 at 10:37
  • 1
    just `$event` not `$event.value` – Langley Jan 15 '16 at 10:39
  • console.log is undefined. – Gary Jan 15 '16 at 10:53
  • you might want to update your code to the way you have it now – Langley Jan 15 '16 at 10:55