Угловые условные компоненты из общего источника - PullRequest
0 голосов
/ 09 декабря 2018

Прежде всего, я хотел бы отметить, что я не угловой разработчик, почти весь мой набор навыков относится к серверной работе, но я пытаюсь разработать эту концепцию, и я даже не знаю, является ли онавозможный.Поиск в Google не очень помогает, потому что я даже не знаю, как правильно сформулировать вопрос, поэтому я надеюсь описать ситуацию, что я хотел бы сделать, как бы я хотел, чтобы это работало, и, надеюсь, получить некоторыесовет о том, что я пытаюсь сделать, на самом деле называется в мире Angular, возможно ли это, и если это возможно, пример того, как это будет выглядеть.

У нас есть SPA с .NETБазовый интерфейс Web API.Существует конечная точка API, /api/feedItems, которая возвращает список «элементов канала», грубый эквивалент журналов событий.

Основная форма элемента канала похожа на это:

export enum FeedItemType {
    undefined = "undefined",
    foo = "foo",
    bar = "bar"
}

export class FeedItemModel {
    id: number;
    createdUtcTimestamp: Date;
    feedType: FeedItemType;
    feedData: {} // object? any?
}

Идея здесь заключается в том, что все элементы фида будут иметь определенные метаданные, включая идентификатор, метку времени, идентификатор типа фида и полезную нагрузку.Фактическое содержимое полезной нагрузки будет отличаться в зависимости от FeedItemType.

Пример списка элементов фида, возвращаемого из вызова API, может выглядеть примерно так:

[  
    {  
    "id":12345,
    "createdUtcTimestamp":"2018-12-05T13:30:00Z",
    "feedType":"foo",
    "feedData":{  
        "name":"this is a foo type feed",
        "description":"This foo feed is describing an event of type 'foo'"
    }
    },
    {  
    "id":67890,
    "createdUtcTimestamp":"2018-12-06T15:45:00Z",
    "feedType":"bar",
    "feedData":{  
        "value1":11111,
        "value2":22222,
        "value3":33333
    }
    }
]

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

Я хочу иметь угловой компонент, отвечающий за выбор списка элементов фида.из API и циклически перебирая элементы фида.Для каждого элемента фида (предположительно, в директиве *ngFor) он должен отображать общие свойства, а затем, на основе feedType, отображать другой «подчиненный» компонент.

В этом случае, скажем,Мой компонент контейнера выглядит следующим образом:

<div class="feed-item-container" *ngFor="let feedItem of feedItemList; let i = index;">
    <div class="feed-item">
        <div class="timestamp-display">{{feedItem.createdUtcTimestamp}}</div>

        <!-- equivalent of "if feedItem.feedType == 'foo'", 
        possibly ngIf or ngSwitch, but I'd prefer to not 
        have to explicitly check for each type -->
        <feed-item-foo (I have no idea how to pass the feedData to this component) />

        <!-- equivalent of "if feedItem.feedType == 'bar'" -->
        <feed-item-bar (again, this is a mystery what should go here) />

        <!-- equivalent of "if can't match on feedType" -->
        <feed-item-generic (something) />
    </div>
</div>

Идея здесь заключается в том, что я могу создавать компоненты вне этого файла по мере необходимости, не внося много изменений (желательно ни одного) в шаблон контейнера.Было бы идеально, если бы я мог программно распознавать feedType, искать для него зарегистрированный селектор компонентов и автоматически передавать ему feedData, но если мне нужно вручную ссылаться на каждый компонент в этом контейнере, это тоже нормально.Я просто не хочу помещать всю логику рендеринга в этот контейнер, так как это очень быстро станет громоздким и сложным в управлении.

Компоненты элемента фида будут иметь свое собственное форматирование, основанное на типе фида, стакже разные стили и, возможно, разные логические операции.Мне не нужен гигантский контейнерный компонент feedItem.

Итак, возможно ли это?Если так, как бы я поступил об этом?

1 Ответ

0 голосов
/ 09 декабря 2018

если бы я мог правильно понять, может быть, вам поможет следующая идея ... Я беру ваш пример и немного его изменяю.

<div class="feed-item-container" *ngFor="let feedItem of feedItemList; let i = index;">
<div class="feed-item">
    <div class="timestamp-display">{{feedItem.createdUtcTimestamp}}</div>

    <!-- equivalent of "if feedItem.feedType == 'foo'", 
    possibly ngIf or ngSwitch, but I'd prefer to not 
    have to explicitly check for each type -->

    <!-- i do not know of any alternative, but to make it a bit more readable
    you can use <ng-container>

    <ng-container *ngIf="feedItem.feedType === 'foo'">
        <!-- you can create your own component and add an @Input() data, so your component will know what it is dealing with (see example below)
        <feed-item-foo [data]="feedItem"/>
    </ng-container>

    <!-- equivalent of "if feedItem.feedType == 'bar'" -->
    <ng-container *ngIf="feedItem.feedType === 'bar'">
        <!-- you can create your own component and add an @Input() data, so 
        your component will know what it is dealing with (see example below)
        <feed-item-bar [data]="feedItem"/>
    </ng-container>
    <!-- equivalent of "if can't match on feedType" -->
    <!-- that is a bit of a pain in the ... --> 
   <ng-container *ngIf='!foo && !bar && !xyz'>
    <feed-item-generic (something) />
   </ng-container>

</div>

Ваши компоненты могут и должны включать всечто-то вроде «базового» класса

export class FeedItemBase implements OnInit {
  @Input() data = <YourType>null; // that is a little hack to get the type 
  // correct (was some bug in a angular 4 version as far as i remember)
  constructor() {
  }
  ngOnInit() {
    // if needed .. if not, delete it :)
  }
}

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

export class FeedItemFoo extends FeedItemBase implements OnInit {
  constructor() {
  }
  ngOnInit() {
    // here you can access data already 
  }
}

, если у вас есть только2 типа (в чем я сомневаюсь) вы также можете сделать что-то подобное:

<div class="feed-item-container" *ngFor="let feedItem of feedItemList; let i = index;">
<div class="feed-item">
    <div class="timestamp-display">{{feedItem.createdUtcTimestamp}}</div>

    <!-- equivalent of "if feedItem.feedType == 'foo'", 
    possibly ngIf or ngSwitch, but I'd prefer to not 
    have to explicitly check for each type -->

    <!-- i do not know of any alternative, but to make it a bit more readable
    you can use <ng-template>
    <ng-container *ngIf="feedItem.feedType === 'foo'; then fooId;else barId"> 
    </ng-container>

   <ng-template #fooId>
        <!-- you can create your own component and add an @Input() data, so your component will know what it is dealing with (see example below)
        <feed-item-bar [data]="feedItem"/>
    </ng-template>

    <!-- equivalent of "if feedItem.feedType == 'bar'" -->
    <ng-template #barId>
        <!-- you can create your own component and add an @Input() data, so 
        your component will know what it is dealing with (see example below)
        <feed-item-foo [data]="feedItem"/>
    </ng-container>
    <!-- equivalent of "if can't match on feedType" -->
    <!-- that is a bit of a pain in the ... --> 
   <ng-container *ngIf='!foo && !bar && !xyz'>
    <feed-item-generic (something) />
   </ng-container>

</div>

Надеюсь, это поможет:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...