Динамическое добавление компонента внутри другого компонента

#angular

#angular

Вопрос:

У меня есть компонент, который отправляет пользовательский ввод (текст) в службу и получает расширенную версию этого текста. Обогащенный означает, что некоторые слова обогащены информацией. Сервер выдает мне исходный текст и список расширенных подстрок, каждая из которых имеет начальный и конечный индексы исходного текста, чтобы я мог найти их в исходном тексте.

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

В Angular 1 у меня была директива, в которой я динамически создавал шаблон, перебирая найденные фразы и создавая новую кнопку для каждой из них между не обогащенными фразами. С помощью $compile() они отображались правильно. Кнопка сама по себе была директивой, поэтому код выглядел следующим образом:

 var newButton = angular.element(
      '<special-button '  
      'enriched="foundPhrases['   i   ']" '  
      'title="''   original.substring(start, end))   ''" '  
      'position="'bottom'"'  
      '></special-button>'
    );
  

Пока все хорошо, но я не нашел способа динамического добавления компонентов в текст в Angular 2.

Я создал компонент, который генерирует HTML, а затем добавляет его с this.elementRef.nativeElement.appendChild(generated)) к элементу компонента. Код, который создает generated , содержит следующие строки для создания специальной кнопки:

 let button = this.renderer.createElement(el, 'special-button');
button.setAttribute('[enriched]', 'foundPhrases['   i   ']');
button.setAttribute('[title]', text.substring(start, end));
button.setAttribute('[position]', ''bottom'');
  

Но эти строки выдают ошибку во время выполнения:

 Error: Failed to execute 'setAttribute' on 'Element':
    '[enriched]' is not a valid attribute name.
  

Как я могу произвольно добавлять свои компоненты в другой компонент с привязкой к данным?

Комментарии:

1. Не лучше ли было бы решить эту проблему с помощью директивы ngIf или ngShow, а не добавлять новый элемент?

2. Можете ли вы уточнить? Клиент не знает, сколько кнопок внутри возвращаемого текста он должен отображать, поэтому, я думаю, статический ngIf слишком ограничен.

3. ngIf с вложенным ngrepeat, чтобы показать, сколько кнопок вам нужно?

4. Но над чем мне выполнять итерацию? Он должен поместить исходный текст в p элемент, а подстроки из обогащенных элементов должны быть button s.

Ответ №1:

Надеюсь, это в какой-то степени удовлетворяет тому, чего вы пытаетесь достичь. Прямое манипулирование DOM не является хорошей практикой в Angular.

Предположим, у вас есть объектная фраза, которая включает оригинал и текст, который «обогащен»

 export class Phrase {
    enriched: string;
    original: string;
    constructor (_enriched: string, _original: string, start: int, end: int){
        this.enriched=_enriched;
        this.original=_original.substring(start, end);
    }
}
  

затем у вас есть enriched-phrases компонент с шаблоном, который включает исходный текст в ngIf, который будет удален после того, как ваша серверная часть получит обогащенный текст и сохранится в array foundPhrases

 @Component({
    selector: 'enriched-phrases'
    template: '<p *ngIf="!foundPhrases.length"/> ' 
              '<special-button *ngIf="foundPhrases.length"' 
              ' *ngFor="let phrase of foundPhrases" [phrase]="phrase" ' 
              '[position]="'bottom'"/>'
})
export class EnrichedPhrasesComponent{
    onGotPhrases(foundPhrases: Array<Phrase>):void {
        this.foundPhrases = foundPhrases;
    }
    foundPhrases: Array<Phrase>;
    orginalText = "original text block";
}
  

И тогда у вас есть компонент для special-button элемента.

 @Component({
    selector: 'special-button',
    template: '<p>{{phrase.original}}</p><button>{{phrase.enriched}}</button>'
}

export class EnrichedPhraseDetail{
    @Input()
    phrase: Phrase;
    position: string;

}
  

Таким образом, компонент специальной кнопки будет заполнен данными после его извлечения, и с помощью директивы ngFor на специальной кнопке это будет повторяться для стольких «фраз», которые у вас есть.

Примечание: На самом деле я никогда не использовал typescript, поэтому там могут возникнуть некоторые синтаксические проблемы, но это суть того, что я пытался объяснить.