Angular2 строки таблицы как компонент

100

Экспериментирую с angular2 2.0.0-beta.0

У меня есть таблица, и содержимое строки создается angular2 следующим образом:

    <table>
        <tr *ngFor="#line of data">
            .... content ....
        </tr>
    </table>

Теперь это работает, и я хочу инкапсулировать контент в компонент «table-line».

    <table>
        <table-line *ngFor="#line of data" [data]="line">
        </table-line>
    </table>

А в компоненте шаблон имеет содержимое <tr> <td>.

Но теперь таблица больше не работает. Это означает, что содержимое больше не отображается в столбцах. В браузере инспектор показывает мне, что элементы DOM выглядят так:

    <table>
        <table-line ...>
            <tbody>
                <tr> ....

Как я могу заставить это работать?

Fbenoit
источник

Ответы:

111

использовать существующие элементы таблицы как селектор

Элемент таблицы не позволяет использовать <table-line>элементы как дочерние элементы, и браузер просто удаляет их, когда находит их. Вы можете обернуть его в компонент и по-прежнему использовать разрешенный <tr>тег. Просто используйте "tr"как селектор.

с помощью <template>

<template>также должно быть разрешено, но пока работает не во всех браузерах. Angular2 на самом деле никогда не добавляет <template>элементы в DOM, а только обрабатывает их внутренне, поэтому это также можно использовать во всех браузерах с Angular2.

Селекторы атрибутов

Другой способ - использовать селекторы атрибутов

@Component({
  selector: '[my-tr]',
  ...
})

использоваться как

<tr my-tr>
Гюнтер Цёхбауэр
источник
Поэтому я бы создал свой компонент TableItemComponent с помощью selector = 'tr'. Но как можно использовать «tr» в других местах для решения других проблем?
fbenoit 01
6
Если родительский компонент включает ваш настраиваемый trтег, он будет использован, в противном случае - поведение браузера по умолчанию. Вы также можете добавлять атрибуты или классы в свой селектор компонентов, например, <tr line-item>с помощью селектора компонентов "tr[line-item] "или <tr class="line-item">селектора компонентов tr.line-item. Таким образом, у вас будет полный контроль. Я сам еще не пробовал ничего из этого в Angular2, но уверен, что это работает.
Günter Zöchbauer 01
5
Есть ли у этого реальный недостаток? Он отлично работает, однако настройки по умолчанию для tslintпрямого меня к руководству по стилю рекомендуя против этого. Мне не нравится отключать рекомендуемые правила линтинга, но, насколько я могу судить, это кажется довольно произвольным стилевым правилом и неизбежным в некоторых ситуациях (например, проблема OP)
Роб
1
Я почти уверен, что здесь нет никаких недостатков, за исключением того, что селекторы элементов встречаются гораздо чаще и поэтому должны использоваться по умолчанию. Если есть допустимый случай, например элементы таблицы или что- <li>то подобное, я не вижу причин, почему бы не использовать его.
Гюнтер Цохбауэр
2
Использование в моем селекторе компонентов tr [line-item] сработало и соответствует правилу руководства по стилю Angular STYLE 05-03, на которое жалуется tslint.
CM
31

Я нашел этот пример очень полезным, но он не работал в сборке 2.2.3, поэтому после долгой царапины в голове он снова заработал с небольшими изменениями.

import {Component, Input} from '@angular/core'

@Component({
  selector: "[my-tr]",
  template: `<td *ngFor='let item of row'>{{item}}</td>`    
})
export class MyTrComponent {
  @Input("line") row:any;
}

@Component({
  selector: "my-app",
  template: `<h1>{{title}}</h1>
  <table>
    <tr  *ngFor="let line of data" my-tr [line]="line"></tr>
  </table>`

})
export class AppComponent {

  title = "Angular 2 - tr attribute selector!";
  data = [ [1,2,3], [11, 12, 13] ];
  constructor() { console.clear(); }
}
DudeOfDoom
источник
1
Отличный ответ. Мне просто нужно было добавить MyTrComponentв, app.module.tsи все работает нормально.
Тито Лейва
26

Вот пример использования компонента с селектором атрибутов:

import {Component, Input} from '@angular/core';
@Component({
  selector: '[myTr]',
  template: `<td *ngFor="let item of row">{{item}}</td>`
})
export class MyTrComponent {
  @Input('myTr') row;
}
@Component({
  selector: 'my-app',
  template: `{{title}}
  <table>
    <tr *ngFor="let line of data" [myTr]="line"></tr>
  </table>
  `
})
export class AppComponent {
  title = "Angular 2 - tr attribute selector";
  data = [ [1,2,3], [11, 12, 13] ];
}

Вывод:

1   2   3
11  12  13

Конечно, шаблон в MyTrComponent будет более сложным, но вы поняли идею.

Старый (beta.0) плункер .

Марк Райкок
источник
Можно ли визуализировать компонент ng без корневого тега? Что-то вроде <! - / ko -> в Knockout.js.
Ssss
@PashaPasha см stackoverflow.com/questions/34280475/...
Марк Rajcok
14
Это вообще не работает (пробовал с angular 2.3). Ошибка брошено:Error: Uncaught (in promise): Error: Template parse errors: Can't bind to 'myTr' since it isn't a known property of 'tr'.
Vukasin
Чтобы он заработал, вам нужно добавить [] в Селектор. Не забывай об этом.
AF С
6

Добавление display: contents в стиль компонента сработало для меня.

CSS:

.table-line {
    display: contents;
}

HTML:

<table>
    <table-line class="table-line" [data]="line">
    </table-line>
</table>

Почему это работает?

При создании экземпляра компонента angular (после компиляции) обертывает содержимое компонента в DOM следующим образом:

<table>
    <table-line>
        <tr></tr>
    </table-line>
</table>

Но для правильного отображения таблицы trтеги нельзя ничем обернуть.

Итак, мы добавляем display: contentsк этому новому элементу. Насколько я понимаю, это означает, что проводник сообщает, что этот тег не должен отображаться, и отображает внутреннее содержимое, как если бы не было обертывания. Таким образом, хотя тег все еще существует, он не влияет на визуально таблицу, а trтеги обрабатываются так, как если бы они были прямыми дочерними элементами tableтега.

Если вы хотите подробнее узнать, как работает контент: https://bitsofco.de/how-display-contents-works/

Рубен Негредо
источник
1
По возможности постарайтесь предоставить дополнительные объяснения, а не просто код. Такие ответы, как правило, более полезны, поскольку они помогают членам сообщества, особенно новым разработчикам, лучше понять обоснование решения и могут помочь предотвратить необходимость в ответах на дополнительные вопросы.
Раджан
Привет, @Rajan, спасибо за подсказку. Я только что обнаружил, как contentsработает, поэтому я не хотел помещать туда информацию, основанную на ложных предположениях ... Я добавил объяснение, как я его понимаю, но если кто-то заметит, что в нем есть ошибка, пожалуйста, не стесняйтесь указать на это ^ ^. Я также добавил ссылку, чтобы люди могли продолжить расследование ... Одна вещь, которую я заметил, хотя там говорится, что это не работает в IE11, я попробовал это на IE 11.657.18362.0, и он работал нормально (но, поскольку я используя angular, где-то может быть полифилл, поэтому я не могу гарантировать его 100% в других средах)
Рубен Негредо,
Очень хороший ответ. ИМО, это следует принять.
adamsfamily
-3

попробуй это

@Component({
    selecctor: 'parent-selector',
    template: '<table><body><tra></tra></body></table>'
    styles: 'tra{ display:table-row; box-sizing:inherit; }'
})
export class ParentComponent{
}

@Component({
    selecctor: 'parent-selector',
    template: '<td>Name</td>Date<td></td><td>Stackoverflow</td>'
})
export class ChildComponent{}
Matsteel
источник