我有一个小应用,其中我收到一个带有一些隐藏单词的问题,像这样写下来:
publishOn()
接收到此字符串后,每个 The {0} {1} {2} his {3} off
字符串都必须替换为用户输入的正确答案。为此,我创建了以下代码:
HTML部分
{x}
打字稿功能
<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) {}
可能无法正常工作,因为我没有按照建议的here使用任何byPassSecurityHtml
。但是,由于我需要以动态方式创建它,并且需要在DOM中将它称为foreach 问题,所以我不知道如何正确使用它...
有人可以帮我吗?
答案 0 :(得分:1)
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' ]
形式的多个部分,然后将其传递给map方法,该方法为每个部分生成一个统一的对象。任何具有字符串“ {”的部分都被视为输入的占位符,因此它将变成{ 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
属性。
答案 1 :(得分:0)
这不是您应该使用Angular的方式。
在Angular中,您不会自己操纵DOM。您应该让框架为您处理。
对于您的问题,我认为最好的解决方案是在原始字符串上使用管道,以免对其进行修改。
答案 2 :(得分:0)
基于@Avin Kavish的目的,我找到了这个最简单的解决方案:
打字稿部分
createQuestion(question: QuestionDto): Array<string> {
let words = question.correctAnswer.split(' ');
return words;
}
返回一个包含所有分隔元素的字符串数组。它返回以下内容:
["The", "{0}", "{1}", "{2}", "his", "{3}", "off"]
HTML部分 在UI部分中,我检查了内容数组,以便决定是否绘制输入或文本。
<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>