首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在经过清理的输入上编写代码?

如何在经过清理的输入上编写代码?
EN

Stack Overflow用户
提问于 2019-06-03 22:37:46
回答 3查看 212关注 0票数 0

我有一个小应用程序,在其中我收到一个问题,其中有一些隐藏的单词要写下来,如下所示:

代码语言:javascript
复制
 The {0} {1} {2} his {3} off

当接收到此字符串时,必须将每个{x}字符串替换为用户将用正确答案填充的输入。因此,我创建了以下代码:

HTML部件

代码语言:javascript
复制
<div *ngFor="let question of questionsArray">
     ---- some stuff ----
    <div [innerHTML]="createQuestion(question)"></div>
     ---- some stuff ----
</div>

Typescript函数:

代码语言:javascript
复制
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,如下所示:

代码语言:javascript
复制
 constructor(private sanitizer: DomSanitizer) {}

它工作得很好,并像这样绘制输入:

但是我不能在输入上写任何东西。我猜可能是因为我没有按照建议的byPassSecurityHtml使用任何Pipe,所以here可能无法正常工作。但是,因为我需要以动态的方式创建它,因为我的DOM中的每个问题都需要调用它,所以我不知道如何正确使用它……

有人能帮我一把吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-06-03 23:25:59

DOM字符串的问题在于,即使它们是由浏览器呈现的,Angular也不会将它们视为视图绑定模板的一部分。解决这个问题的最好方法是使用一个数组,它定义了模板应该如何呈现,如下所示:

代码语言:javascript
复制
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: 'text', value: 'text value here' }形式。任何文本都会转换为形式ngIf,这样我们以后就可以遍历此数组,并使用*ngIf有条件地呈现文本或输入。

这是为您提供的示范性字符串生成的模板。

代码语言:javascript
复制
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' }
]

使用此模板,您可以创建一个值绑定角度模板,如下所示:

代码语言:javascript
复制
<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指令遍历模板的每个部分,并根据每个部分的type属性生成spaninput。如果类型为text,则显示跨度。如果类型为input,并且输入与绑定到value属性的ngModel一起显示。

票数 1
EN

Stack Overflow用户

发布于 2019-06-03 23:01:11

这不是你应该如何使用Angular的。

在Angular中,您不需要自己操作DOM。你应该让框架为你处理这个问题。

对于你的问题,我认为最好的解决方案是在你的原始字符串上使用管道,而不是修改它。

Here is some stackblitz so that you can see it in action

票数 0
EN

Stack Overflow用户

发布于 2019-06-04 15:53:56

基于@Avin Kavish的目的,我找到了这个最简单的解决方案:

Typescript部件

代码语言:javascript
复制
createQuestion(question: QuestionDto): Array<string> {
    let words = question.correctAnswer.split(' ');
    return words;
}

返回包含所有分隔元素的字符串数组。它返回以下内容:

代码语言:javascript
复制
 ["The", "{0}", "{1}", "{2}", "his", "{3}", "off"]

HTML part在UI part中,我检查内容数组,以决定是绘制输入还是绘制文本。

代码语言:javascript
复制
<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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56429590

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档