Angular 2 предава събитие за щракване към генеричен компонент за многократна употреба

Имам няколко компонента, които използват основно една и съща таблица, така че съм в процес на абстрахиране на тази таблица. Реших повечето от моите нужди от популация на динамични таблици, но все още не съм намерил решение за следното.

В един от екземплярите на моята таблица редовете трябва да могат да се кликват. В оригиналната таблица просто добавих събитие за щракване в реда и го накарах да извика функция в моя машинописен файл.

Сега, когато таблицата е дъщерна на всеки консумиращ компонент, не съм сигурен как да добавя динамично това събитие за кликване. Ето какво по същество се опитвам да постигна:

HTML:
<tr class="someClass" <!-- want click event here -->>
  <td *ngFor="let column of row;"><div [innerHtml]="column"></div></td>
</tr>

Това е файлът с typescript на таблиците, където всички данни влизат в обекта visibleData:

export class GenericTableComponent implements OnInit {
    @Input() visibleData;
    constructor() { }

    ngOnInit() {
    }
}

Тук внедрявам общата таблица в моя родителски HTML

Parent HTML:
<oma-generic-table [visibleData]="visibleData"></oma-generic-table>

И тук има функция в родителя, която подготвя данните. Опитах се да запазя събитието за щракване в низ и да го предам, но всичко, което опитах досега, се провали (свързване на данни с {{}}, квадратни скоби и т.н.).

transformData(visibleData) {
    const ret: any = {};
    ret.headings = visibleData.headings;
    ret.action = '(click)="rowClicked([row.id])"';
    ret.checkbox = this.checkBox;                                                   //add if the table needs checkboxes
    ret.content = [];
    for (let i = 0; i < visibleData.content.length; i++) {
        ret.content.push(_.values(_.omit(visibleData.content[i], 'id')));
    }
    return ret;
}

Въпреки това, дори когато е твърдо кодирано в дъщерния елемент, събитието за кликване не разпознава функцията в родителския елемент и получавам следната грешка:

EXCEPTION: Error in ./GenericTableComponent class GenericTableComponent - inline template:35:4 caused by: self.parentView.context.rowClicked is not a function
ORIGINAL EXCEPTION: self.parentView.context.rowClicked is not a function

Не съм сигурен дали това е нещо просто или не. Нов съм в Angular 2, така че се извинявам, ако този въпрос е опростен. Благодаря предварително за всяка помощ.


person Chris Sharp    schedule 22.02.2017    source източник


Отговори (3)


Вашата обща таблица може да излъчва персонализирани събития, за които родителският компонент може да се абонира:

@Component({
    selector: 'oma-generic-table',
    template: `
        <table>
            <tr *ngFor="let row of visibleData" class="someClass" (click)="selectRow(row)">
              <td *ngFor="let column of row;"><div [innerHtml]="column"></div></td>
            </tr>
        </table>
    `
})
export class OmaGenericTable {

    @Input() visibleData: VisibleDataRow[];

    @Output() select = new EventEmitter<VisibleDataRow>();

    selectRow(row: VisibleDataRow) {
        this.select.emit(row);
    }
}

След това във вашия родителски компонент:

// in template
<oma-generic-table 
        [visibleData]="visibleData" 
        (select)="tableRowSelected($event)"
></oma-generic-table>

// in component
tableRowSelected(r: VisibleDataRow) {
    console.log(`Selected row ${r}`);
}
person Vilmantas Baranauskas    schedule 22.02.2017
comment
Благодаря ви за това елегантно решение. Имам няколко въпроса. 1. Къде се декларира „VisibleDataRow“? Преданият обект е сложен обект, който включва заглавията на таблицата и масивите от редове, с някои други свойства. Не съм сигурен какво представлява VisibleDataRow или дали първоначалното ми обяснение не беше достатъчно. Извинения, ако е било подвеждащо. 2. За да направя функцията за кликване незадължителна, обмислях просто да предам низ от 'style=cursor: pointer' с всички родители, които желаят да направят редовете с възможност за кликване. Това хакерски подход ли е? Благодаря отново! - person Chris Sharp; 22.02.2017
comment
1. Тъй като не сте посочили никакъв тип редове във вашия въпрос, аз просто използвах VisibleDataRow, за да го представя. visibleData е масив от всякакъв вид обекти, които може да имате. 2. Можете да добавите друг входен параметър [selectable]=true, за да активирате/деактивирате избора на ред в таблицата. Вътре във вашия OmaGenericTableComponent можете да обвържете необходимия css клас въз основа на този входен параметър, като използвате @HostBinding('class.selectable') @Input() избираем: булев; декларация. - person Vilmantas Baranauskas; 23.02.2017

Angular2, доколкото знам, няма да се свърже със събитие "(щракване)" по този начин. Може да изглежда грозно, но бих добавил директивата NgIf към таблицата на реда, върху който трябва да действа събитието за щракване, и обратно да приложа логиката към друг ред, който не трябва да бъде засегнат от събитие за щракване. Пример:

<tr *ngIf="!isClickable" class="someClass"> <tr *ngIf="isClickable" class="someClass" (click)="rowClicked()> <td *ngFor="let column of row;"><div [innerHtml]="column"></div></td> </tr>

След това можете да подадете променливата isClickable като вход във вашата таблица от всяко място, където инстанциирате компонента на таблицата, и да действате спрямо него.

person Devon Germano    schedule 22.02.2017

Използване на това в HTML

<tr *ngIf="!isClickable" class="someClass">
 <tr *ngIf="isClickable" class="someClass" #click>
  <td *ngFor="let column of row;"><div [innerHtml]="column"></div></td>
 </tr>

това на машинопис

export class GenericTableComponent implements OnInit {
    @Input() visibleData;
    @ViewChild('click') protected _click:ElementRef;

    constructor(enderer: Renderer) {
        renderer.listen(this._click.nativeElement, 'click', (event) => {
            // Do something with 'event'
        })
    }
}

Надявам се това да ви помогне

person Youngz ie    schedule 22.02.2017