使用viewContainerRef.CreateComponent(),然后添加数据时,InnerHTML没有属性数据

发布于 2025-02-05 07:37:15 字数 2477 浏览 4 评论 0 原文

问题 - 我正在将ViewContainerRef传递到我的构造函数中,以实例化一个名为“ MemberCardComponent”的组件。然后,我试图用输入数据填充它,但是没有将数据填充到InterHTML中。

stackblitz - 我已经设置了这个SB证明我的问题: stackblitz link

const component = this.viewContainerRef.createComponent(MemberCardComponent);
component.instance.MemberCard = memberData; // memberData fetched from Db
const memberCardHtml = component.location.nativeElement.innerHTML; // innterHTML doesn't have MemberCard data.

看起来像这样的属性:

@Input() set MemberCard(member: IMemberCard) {
    this.member = member;
}

我看到内部HTML并未填充任何数据。所有字段都是空的,应该有会员数据。前任。 photourl,name等

问题 - 我还需要执行其他操作以将我的输入数据传达到InterHTML中吗?

这是我悬停在innerhtml上时看到的。

'<div _ngcontent-yft-c87="" class="card"><div _ngcontent-yft-c87="" class="row g-0 row-eq-height"><div _ngcontent-yft-c87="" class="col-md-4"><picture _ngcontent-yft-c87=""><source _ngcontent-yft-c87="" media="(min-width: 0px) and (max-width: 350px)"><source _ngcontent-yft-c87="" media="(min-width: 351px) and (max-width: 720px)"><source _ngcontent-yft-c87="" media="(min-width: 721px) and (max-width: 1001px)"><source _ngcontent-yft-c87="" media="(min-width: 1002px)"><img _ngcontent-yft-c87="" alt…"float-end"></span></div><div _ngcontent-yft-c87="" class="col-12"><span _ngcontent-yft-c87="">Experience</span><span _ngcontent-yft-c87="" class="float-end"></span></div><div _ngcontent-yft-c87="" class="col-12"><span _ngcontent-yft-c87=""></span><span _ngcontent-yft-c87="" class="float-end"></span></div><div _ngcontent-yft-c87="" class="col-12"><span _ngcontent-yft-c87="">Education</span><span _ngcontent-yft-c87="" class="float-end"></span></div></div></div></div></div><!--container--></div>'

fyi - 我正在尝试创建组件的字符串表示形式以填充Swiper.js幻灯片。这是另一个所以我创建了我创建的解释了为什么我需要组件的字符串表示。

Problem - I'm passing a ViewContainerRef into my constructor to instantiate a component named 'MemberCardComponent'. Then I'm trying to fill it with input data, but no data is being populated into the innerHTML.

Stackblitz - I've setup this SB demonstrate my issue:
Stackblitz link

const component = this.viewContainerRef.createComponent(MemberCardComponent);
component.instance.MemberCard = memberData; // memberData fetched from Db
const memberCardHtml = component.location.nativeElement.innerHTML; // innterHTML doesn't have MemberCard data.

MemberCard is an input property that looks like this:

@Input() set MemberCard(member: IMemberCard) {
    this.member = member;
}

I see the inner html isn't filled with any of the data. All the fields are empty, where there should be member data. Ex. photoUrl, name, etc

QUESTION - Is there some other action I need to perform to get my input data into the innerHTML?

Here is what I see when I hover over the innerHtml.
enter image description here

'<div _ngcontent-yft-c87="" class="card"><div _ngcontent-yft-c87="" class="row g-0 row-eq-height"><div _ngcontent-yft-c87="" class="col-md-4"><picture _ngcontent-yft-c87=""><source _ngcontent-yft-c87="" media="(min-width: 0px) and (max-width: 350px)"><source _ngcontent-yft-c87="" media="(min-width: 351px) and (max-width: 720px)"><source _ngcontent-yft-c87="" media="(min-width: 721px) and (max-width: 1001px)"><source _ngcontent-yft-c87="" media="(min-width: 1002px)"><img _ngcontent-yft-c87="" alt…"float-end"></span></div><div _ngcontent-yft-c87="" class="col-12"><span _ngcontent-yft-c87="">Experience</span><span _ngcontent-yft-c87="" class="float-end"></span></div><div _ngcontent-yft-c87="" class="col-12"><span _ngcontent-yft-c87=""></span><span _ngcontent-yft-c87="" class="float-end"></span></div><div _ngcontent-yft-c87="" class="col-12"><span _ngcontent-yft-c87="">Education</span><span _ngcontent-yft-c87="" class="float-end"></span></div></div></div></div></div><!--container--></div>'

FYI - I'm trying to create the string representation of the component to populate a swiper.js slide. Here is another SO post I created that explains why I need the string representation of my component.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

悍妇囚夫 2025-02-12 07:37:15
tl; dr:添加模板,以便可以评估和渲染组件。

您不建议使用 InnerHtml 的方法,因为 createComponent 将与模板一起使用。

为了实现预期的结果我已经修复了您stackblitz示例,它显示了使用这两种方法的预期行为,但是 inninhtml方法需要与包装器一起使用,因此 testComponent 更改eTector有机会使用渲染变量值。

我所做的主要更改是:

  1. 添加了一个自定义模板,因此 testCompnent 值可以是
    评估
@ViewChild('customTemplate', { read: ViewContainerRef, static: true })
customTemplate: ViewContainerRef;
  1. viewContainerRef 内容到 template 使其得到渲染,,否则无法获得其HTML
this.customTemplate.insert(this.viewContainerRef.get(0))
  1. 添加 detectChanges 评估父母及其子女的检测更改的代码>
detectChanges(): void {
  if (this.customComponent?.changeDetectorRef) {
    this.customComponent.changeDetectorRef.detectChanges();
  } else {
    if (this.customComponent) {
      console.log('Custom component not ready.');
    }
  }
  this.cdr.detectChanges();
}

可以做更多的方法,我对此进行了回答,因为您的代码更合适地适合它。


同样,

对于不建议使用 innerhtml 的建议解决方案,必须进行以下更改:

  1. 上一个解决方案中提到的所有内容,因为
    没有其他方法(我知道)渲染和评估组件。
  2. 包装器DOM,因此您可以提取其评估的 innerhtml
  3. a domsatinizer 可以渲染DOM,直接的HTML代码注入是“禁止的”,您必须明确地显式告诉你你愿意接受
    使用它的风险。
  4. 更改 texthtml 字符串 safe> safehtml 的值类型,因此其接受消毒值
  5. 以使其工作,您需要隐藏包装器设置 style =“ display:none”
  6. 您可以清洁/销毁或用包装器做任何您想做的事情,因为您已经获得了HTML。
this.testHtml = this.sanitizer.sanitize(
  SecurityContext.HTML,
  this.sanitizer.bypassSecurityTrustHtml(
    document.getElementById('wrapper').innerHTML
  )
);
TL;DR: Add a template so the component can be evaluated and rendered.

Your approach of using innerHTML is not recommended as createComponent is meant to be used together with a template.

To fulfil the expected result I've fixed your Stackblitz example, and it shows the expected behaviour using both approaches, however the innerHTML way needs to be used with a wrapper so the TestComponent changeDetector has a chance to render variable values.

The main changes I did are the following:

  1. Added a custom template so the TestCompnent values can be
    evaluated
@ViewChild('customTemplate', { read: ViewContainerRef, static: true })
customTemplate: ViewContainerRef;
  1. Added the ViewContainerRef content to the template so it gets rendered, otherwise there's no way to get its html
this.customTemplate.insert(this.viewContainerRef.get(0))
  1. Added a detectChanges which evaluates both detection changes from the parent and its child
detectChanges(): void {
  if (this.customComponent?.changeDetectorRef) {
    this.customComponent.changeDetectorRef.detectChanges();
  } else {
    if (this.customComponent) {
      console.log('Custom component not ready.');
    }
  }
  this.cdr.detectChanges();
}

There's more ways that your desired result can be done, I answered with this one because your code was more suitable to be adapted to it.


Also

For the not recommended solution of using innerHTML the following changes were necessary:

  1. Everything that was mentioned in the previous solution, as there's
    no other way (known by me) to render and evaluate components.
  2. A wrapper DOM, so you can extract its evaluated innerHTML
  3. A domSatinizer so the DOM can be rendered, direct html code injection is "forbidden" in Angular, and you have to explicitly tell that you're willing to take
    the risks of using it.
  4. Changing textHtml value type from string to SafeHtml so its accepts sanitized values
  5. For this to work, you'll need to hide the wrapper setting style="display: none"
  6. You can then clean/destroy or do whatever you want with the wrapper as you already got its HTML.
this.testHtml = this.sanitizer.sanitize(
  SecurityContext.HTML,
  this.sanitizer.bypassSecurityTrustHtml(
    document.getElementById('wrapper').innerHTML
  )
);
多情出卖 2025-02-12 07:37:15

您可以将更改EtectionRef 将其注入到 MemberCardComponent 组件,然后在您的父零件中调用 detectchanges()

在触发更改检测之前,您正在尝试获取 innerhtml

这是一个工作示例: stackblitz

You can inject ChangeDetectionRef to MemberCardComponent component and then call detectChanges() in your parent component.

You are trying to get the innerHtml before the change detection is triggered.

here is a working example: Stackblitz

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文