Как написать на Sanitized вход? - PullRequest
0 голосов
/ 03 июня 2019

У меня есть небольшое приложение, в котором я получаю вопрос с несколькими скрытыми словами, которые нужно записать так:

 The {0} {1} {2} his {3} off

Когда эта строка получена, каждая строка {x} должна быть заменена вводом, который пользователь заполнит правильным ответом. Для этого я создал этот код:

HTML часть

<div *ngFor="let question of questionsArray">
     ---- some stuff ----
    <div [innerHTML]="createQuestion(question)"></div>
     ---- some stuff ----
</div>

Функция машинописи

createQuestion(question: string): SafeHtml {
    let innerHtml = '';
    let words = question.split(' ');

    for (let index = 0; index < words.length; index++) {
        const element = words[index];
        if (element.indexOf('{') >= 0) {
            innerHtml += '<input type="text" name="test"></input>';
        } else {
            innerHtml += element;
        }
    }

    return this.sanitizer.bypassSecurityTrustHtml(innerHtml);
}

Я также добавил DomSanitizer в конструктор так:

 constructor(private sanitizer: DomSanitizer) {}

Работает нормально и выводит данные следующим образом:

enter image description here

Но я не могу ничего написать на входе. Я думаю, что, возможно, byPassSecurityHtml может не работать, потому что я не использовал Pipe, как предложено здесь . Но, поскольку мне нужно, чтобы он был создан в динамическом виде, как его нужно называть foreach question в моем DOM, я не могу понять, как правильно его использовать ...

Кто-нибудь может мне помочь?

Ответы [ 3 ]

1 голос
/ 03 июня 2019

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

createQuestion(question: string) {
const template = question.match(/[A-Za-z]+|{\d}/g) // <-- [ 'The', '{0}', '{1}', '{2}', 'his', '{3}', 'off' ]
                  .map(match => match[0] === '{' ? { type: 'input', value: ''}
                  : { type: 'string', value: match })

return template;
}

Метод createQuestion принимает строку шаблона и использует регулярное выражение для разбиения его на части.в форме [ 'The', '{0}', '{1}', '{2}', 'his', '{3}', 'off' ], которую я затем передаю в метод карты, который генерирует единый объект для каждой части.Любая часть, имеющая строку '{', считается заполнителем для ввода, поэтому она превращается в форму { type: 'input', value: '' }, любой текст превращается в форму { type: 'text', value: 'text value here' }, так что мы позже сможем перебрать этот массив и использовать * ngIf.для условного рендеринга либо текста, либо ввода.

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

template = [
  { type: 'text', value: 'The' },
  { type: 'input', value: '' }
  { type: 'input', value: '' }
  { type: 'input', value: '' }
  { type: 'text', value: 'his' }
  { type: 'input', value: '' }
  { type: 'text', value: 'off' }
]

С помощью этого шаблона вы можете создать угловой шаблон со значением, напримерИтак,

<div *ngFor="let template of questionsArray.map(q => createQuestion(q))">
     ---- some stuff ----
    <div *ngFor="let section of template">
    <input *ngIf="section.type === 'input'" ([ngModel])="section.value" />
    <span *ngIf="section.type === 'text'">{{ section.value }}</span>
    </div>
     ---- some stuff ----
</div>

Внешняя директива *ngFor проходит через все различные вопросы, которые были преобразованы в шаблоны с помощью .map(q => createQuestion(q)).Внутренняя директива *ngFor проходит по каждой секции шаблона и генерирует либо span, либо input на основе свойства type каждого раздела.Если тип text, отображается диапазон.Если тип input и ввод отображается с привязкой ngModel к свойству value.

0 голосов
/ 04 июня 2019

Основываясь на цели @Avin Kavish, я нашел самое простое решение:

Часть машинописи

createQuestion(question: QuestionDto): Array<string> {
    let words = question.correctAnswer.split(' ');
    return words;
}

Возвращает массив строк со всеми разделенными элементами.Он возвращает это:

 ["The", "{0}", "{1}", "{2}", "his", "{3}", "off"]

HTML-часть В пользовательском интерфейсе я проверяю массив содержимого, чтобы принять решение, рисовать ли ввод или текст.

<div *ngFor="let question of questionsArray">
    <div *ngFor="let word of createQuestion(question); index as i">
       <input *ngIf="word.includes('{'); else elseBlock"
           id="word-{{i}}"
           class="form-control"
           type="text" />
           <ng-template #elseBlock>{{ word }}</ng-template>
    </div> 
 </div>
0 голосов
/ 03 июня 2019

Это не то, как вы должны использовать Angular.

В Angular вы сами не манипулируете DOM. Вы должны позволить каркасу справиться с этим за вас.

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

Вот несколько стековых бликов, чтобы вы могли увидеть их в действии

...