使用Angular和ANYWHERE将元素动态添加到可编辑div中 [英] Dynamically add elements to the editable div with Angular and ANYWHERE

查看:65
本文介绍了使用Angular和ANYWHERE将元素动态添加到可编辑div中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我正在创建一个HTML界面,用户应该可以在其中编写文本并将其作为通知推送到我们的移动应用.

So, I am creating an HTML interface where user should be able to write a text and push it as a notification to our mobile app.

我正在使用Angular 5处理文本和动态插入的元素时遇到的一些问题;

I am facing some troubleshoots with the text and the dynamic inserted elements using Angular 5;

文本可以包含特殊元素,例如:电话号码,位置和网站URL.这些特殊元素将通过按一个打开对话框的按钮插入,并针对每个对话框显示其特定字段,例如用于位置的google maps和用于Web URL和移动电话的输入字段.它的实现方式是为了在保存按钮上捕获经度,纬度和电话号码,以便将它们作为按钮添加到设备上接收到的推送中.

The text can contain special elements like: phone number, Location and website URL. Those special elements will be inserted by pressing on a button that opens a dialog, and for each one its specific fields are displayed, like google maps for location and input fields for Web URL and mobile Phone. It is implemented this way in order to capture longitude, latitude and phone numbers on save button in order to add them as buttons to the received push on the devices.

无论如何,上述方法可以实现,并且可以成功完成,除了在Web界面的div内动态添加特殊元素的跨度的方式之外.添加的跨度必须具有一个类和一个click事件,才能再次显示该对话框以修改数据.也可以根据用户的选择将它们插入到大div内的任何位置.

Anyway, the above is implemented and could work successfully except the way of adding dynamically spans of special elements inside the div of the web interface. Spans added must have a class and a click event to display again the dialog in order to modify the data. Also they can be inserted anywhere inside the big div depending on user's choice.

下面是上面描述的图像.

Below is the image of above description.

蓝色范围是应动态添加到内容可编辑div中的范围,该范围可以由大约450个字符填充.

The blue spans, are the ones that should be added dynamically inside the content editable div that can be filled by around 450 characters.

那么如何解决该问题并启用在内容可编辑的div内添加带有图标的可单击和设计的跨度的功能,并能够在最后阶段检索数据?

So how to solve the issue and enable the feature of adding clickable and designed spans with icons inside a content editable div, and be able in a final stage to retrieve data?

下面是我的代码,可以工作,但用于特定/预定义的位置:

My code is the below, working but for a specific/predefined position:

Message.html

      <div id="myMessage" contenteditable="true" dir="ltr" [innerHTML]="contentEN | safeHtml" 
      style=" height: 80px;border: 1px solid #c1c1c1; padding: 7px;">
      </div>
      
      <ng-container  #vc>           
      </ng-container>

Message.ts

      @ViewChild('vc', {read: ViewContainerRef}) target: ViewContainerRef;
      
      createSpanPhone(spanIDNumber, phoneDescription, phoneValue ){
      
          // here the span Phone is created dynamically outside the div
          let phoneComponent = this.cfr.resolveComponentFactory(PhoneComponent);
          this.componentRef = this.target.createComponent(phoneComponent);
      }

PhoneComponent.ts

    import { Component } from '@angular/core';
    import { faPhone } from '@fortawesome/free-solid-svg-icons';

    @Component({
       selector: 'my-phone',
       template: '<span contenteditable="false" (click) = "test()" class="BAN_Tags_IN_Text"> <fa-icon 
                  [icon]="faPhone" class="faSpanIcon"> </fa-icon> <span class="phoneDesc" 
                  data-attr="EN">hello</span> <span class="phoneVal" ><b>12346</b></span>
                   </span>'
      })

   export class PhoneComponent  {
      faPhone = faPhone; // trying the icon

      constructor(){    
      }

     test(){
       console.log("Hiiii"); // trying the click event
     }
   }  

ViewContainerRef已成功填充,但我需要在上面的div(id = myMessage)中填充跨度,而不是在预定义的位置.

The ViewContainerRef is filled successfully but I need to fill spans in the div above (id=myMessage) and not in a predefined position.

推荐答案

如果您的文本是纯文本(没有< span> 不能包含的html标签,-我想要表示允许,例如< i> &b; b> ,但不允许< p> -您可以创建类似

if your text are simple text (don't has html tags that can not enclosed by <span>, -I want to mean that is allowed e.g. <i> or <b>, but not <p> - you can create a component like

@Component({
  selector: "html-content",
  template: `
    <span class="inline" [innerHTML]="value"></span>
  `
})
export class HtmlComponent {
  @Input() value;
  constructor() {}

}

类似的指令

@Directive({ selector: "[content]" })
export class ContentDirective {
  @Input() set content(textHtml: string) {
    this.viewContainerRef.clear();
    if (!textHtml) return
    //If not end with . or space, add an space
    if (textHtml.slice(-1)!=" " && textHtml.slice(-1)!=".")
      textHtml+=" "

    //gets the "words"
    //const parts = textHtml.match(/\ ?\S+\ |\ ?\S+\./gi);

     const parts = textHtml.match(/<?[^\r\n\t\f\v< ]+\ ?/gi);
    parts.forEach(h => {
      let space = false;
      let search = h.replace(/[\ .;,:]/gi, "")
      let arg=null;

      //to allow pass arguments to the components in the way, e.g.
      //     <phone=arguments -be carefull! the arguments can not contains spaces
      //     
      if (search.match(/<phone=.+/))
      {
        arg=search.split("=")[1].split(">")[0]
        search="<phone>"
      }
      if (search.match(/<location=.+/))
      {
        arg=search.split("=")[1].split(">")[0]
        search="<location>"
      }
        
      switch (search) {
        case "<phone>":
        case "<location>":
          const factory =
            search == "<phone>"
              ? this.componentFactoryResolver.resolveComponentFactory(
                  PhoneComponent
                )
              : this.componentFactoryResolver.resolveComponentFactory(
                  LocationComponent
                );

          const phone=this.viewContainerRef.createComponent(factory);
          //if our component has "@Input() arg"
          (phone.instance as any).arg=arg||"";
          break;
        
        default:
          const factoryHtml = this.componentFactoryResolver.resolveComponentFactory(
            HtmlComponent
          );
          const html = this.viewContainerRef.createComponent(factoryHtml);
          html.instance.value = h;
          space = true;
          break;
      }
      //this allow write space or dot after the component.
      if (!space && h.match(/.+>[\ ;,:.]/gi)) {
        const factoryDot = this.componentFactoryResolver.resolveComponentFactory(
          HtmlComponent
        );
        const html = this.viewContainerRef.createComponent(factoryDot);
        //we check if, after the component we has a "," or ";" or ":" or ". "
        html.instance.value = h.slice(h.indexOf(">")+1)
      }
    });
    //just for check the parts
    console.log(textHtml, parts);
  }
  constructor(
    private viewContainerRef: ViewContainerRef,
    private componentFactoryResolver: ComponentFactoryResolver
  ) {}
}

您可以看到没有保证的stackblitz

这篇关于使用Angular和ANYWHERE将元素动态添加到可编辑div中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆