#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, поэтому там могут возникнуть некоторые синтаксические проблемы, но это суть того, что я пытался объяснить.