#html #angular #typescript #angular5
#HTML #angular #typescript #angular5
Вопрос:
Итак, я создаю HTML-интерфейс, в котором пользователь должен иметь возможность писать текст и отправлять его в качестве уведомления в наше мобильное приложение.
Я сталкиваюсь с некоторыми проблемами с текстом и динамическими вставленными элементами с использованием Angular 5;
Текст может содержать специальные элементы, такие как: номер телефона, местоположение и URL-адрес веб-сайта. Эти специальные элементы будут вставлены нажатием кнопки, которая открывает диалоговое окно, и для каждого из них отображаются его конкретные поля, такие как карты Google для определения местоположения и поля ввода для веб-URL и мобильного телефона. Это реализовано таким образом, чтобы фиксировать долготу, широту и номера телефонов на кнопке сохранения, чтобы добавлять их в качестве кнопок к полученному нажатию на устройствах.
В любом случае, описанное выше реализовано и может успешно работать, за исключением способа динамического добавления промежутков специальных элементов внутри div веб-интерфейса. Добавленные области должны иметь класс и событие щелчка, чтобы снова отобразить диалоговое окно для изменения данных. Также они могут быть вставлены в любое место внутри большого div в зависимости от выбора пользователя.
Ниже приведено изображение с описанием выше.
Синие промежутки — это те, которые следует динамически добавлять в редактируемый div, который может быть заполнен примерно 450 символами.
Итак, как решить проблему и включить функцию добавления интерактивных и разработанных разделов со значками внутри редактируемого содержимого div и иметь возможность на заключительном этапе извлекать данные?
Мой код приведен ниже, работает, но для определенной / предопределенной позиции:
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), а не в предопределенной позиции.
Ответ №1:
если ваш текст представляет собой простой текст (не содержит html-тегов, которые не могут быть заключены в <span>
, — я хочу иметь в виду, что это разрешено, например <i>
, или <b>
, но нет <p>
— вы можете создать такой компонент, как
@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)!=" " amp;amp; textHtml.slice(-1)!=".")
textHtml =" "
//gets the "words"
//const parts = textHtml.match(/ ?S | ?S ./gi);
const parts = textHtml.match(/<?[^rntfv< ] ?/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 amp;amp; 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 без гарантии