简体   繁体   English

document.getelementbyid 始终在 angular 13 中返回 null

[英]document.getelementbyid always returns null in angular 13

I have a component like this我有这样的组件

export class NotificationPostComponent extends PostComponent implements OnInit, AfterViewInit {
    commentsDto: IComment[] = [];
    commentId = '';
    ngOnInit(): void {
    this.route.data.subscribe(data=>{
      this.post = data.post;
    });
    this.route.params.subscribe((param : Params) => {
      const slug = param['slug'];      
      this.commentId = param['commentid'];
      this.notifiService.loadCommentsOfPost(slug, this.commentId).subscribe(data=>{
          this.commentsDto = data.comments;       
        })       
    });
    super.ngOnInit();    
  }
  ngAfterViewInit(): void {
    var idDiv = document.getElementById(this.commentId)
    console.log(idDiv)
  }
}

This is a html with id is Guid:这是一个 html,id 是 Guid:

<div id="{{cmt.id}}" *ngFor="let cmt of commentsDto">
  <div>comment</div>
</div>

the problem is that after view is initialized its document.getElementById is always null. Please tell me where did I go wrong?问题是视图初始化后,它的 document.getElementById 总是 null。请告诉我 go 哪里错了?

Instead of using document.getElementById you can use Angular's built-in API: @ViewChildren .除了使用document.getElementById ,您还可以使用 Angular 的内置 API: @ViewChildren

Then, the inline Template could be extracted into a new component.然后,可以将内联模板提取到新组件中。

Template模板

<button (click)="scrollToBottom()">Scroll to last comment</button>

<app-comment [title]="comment.title" *ngFor="let comment of comments$ | async">
</app-comment>

<button (click)="scrollToTop()">Scroll to 1st Comment</button>

In the Component, use ViewChildren to access the collection of your CommentComponents represented by a QueryList .在组件中,使用ViewChildren访问由QueryList表示的CommentComponents 集合

If you need to access the HTML-Element directly, you need to configure @ViewChildren to read the ElementRefence ( @ViewChildren(CommentComponent, { read: ElementRef }) ).如果您需要直接访问 HTML 元素,则需要配置 @ViewChildren 以读取 ElementRefence ( @ViewChildren(CommentComponent, { read: ElementRef }) )。

Component成分

export class NotificationPostComponent extends PostComponent
  implements OnInit, AfterViewInit {
    comments$ = /* Stream of Comments */

    @ViewChildren(CommentComponent, { read: ElementRef })
  commentElementReferences: QueryList<ElementRef<HTMLElement>> | undefined;
}

Next, if you need to scroll to a specific element by a ID or something like that, you can mark each Comment Component with an attr-Binding .接下来,如果您需要通过 ID 或类似的东西滚动到特定元素,您可以使用attr-Binding标记每个评论组件。

Template模板

<app-comment
  [title]="comment.title"
  [attr.data-anchor]="comment.id"
  *ngFor="let comment of comments$ | async"
>
</app-comment>

Now, you can add some logic to your component finding the Element you need, allowing you to scroll to it.现在,您可以向您的组件添加一些逻辑来查找您需要的元素,从而允许您滚动到它。

Component成分

private scrollToCommentById(id: string) {
    if (!this.commentElementReferences) return;

    const commentToScrollTo = this.commentElementReferences
      .map((reference) => reference.nativeElement)
      .find((element) => element.getAttribute('data-anchor') === id);

    commentToScrollTo.scrollIntoView({ behavior: 'smooth' });
  }

Finally, you can connect to the activated route, triggering your scrolling mechanism when navigation kicks in.最后,您可以连接到激活的路线,在导航开始时触发您的滚动机制。

  ngAfterViewInit(): void {
    // Listen to parameter changes in route
    this.activatedRoute.paramMap
      .pipe(
        map((paramMap) => paramMap.get('id')),
        filter((id) => !!id),
        tap((id) => this.scrollToCommentById(id))
      )
      .subscribe();
  }

Demo演示

This StackBlitz @ViewChild Demo shows how everything can be set up. 这个 StackBlitz @ViewChild 演示展示了如何设置所有内容。 There you also see how the button is set up that scrolls to a specific Comment by its ID.您还可以看到按钮是如何设置的,它可以通过 ID 滚动到特定的 Comment。

<!--see the tempalte reference variable "#comment"-->
<div #comment id="{{cmt.id}}" *ngFor="let cmt of commentsDto">
  <div>comment</div>
</div>

//In commentsyou has the "QueryList" (an specie of array)
@ViewChildren('comment') comments:QueryList<ElementRef>

this.notifiService.loadCommentsOfPost(slug, this.commentId).subscribe(data=>{
      this.commentsDto = data.comments;       
      //you neeed wait Angular "render" the elements
      setTimeout(()=>{
        const comment=this.comments
            .find(x=>x.nativeElement.getAttribute('id')==myId)
        if (comment)
            comment.nativeElement.scrollIntoView(
              {Behaivor:"Smooth",Block:Start,inline:"Nearest"})
       })
    })  

Well, you can find using "nativeElement.getAttribute" or find the index of the comment and find the element at this index.好吧,你可以使用“nativeElement.getAttribute”找到或者找到评论的索引并在这个索引处找到元素。 some like有些喜欢

        const index=this.commentsDto.findIndex(x=>x.id==myInd)
        const comment=this.comments
            .find((_,i)=>i==index)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Angular 12 对象在 document.getElementById(elementId) 中可能为“null” - Angular 12 Object is possibly 'null' in document.getElementById(elementId) Angular document.getElementById 不能动态使用插值 - Angular document.getElementById not working with interpolation dynamically angular4 / typescript中的document.getElementById替换? - document.getElementById replacement in angular4 / typescript? 替换 Angular 中的 document.getElementById('checkBox') - Replacing document.getElementById('checkBox') in Angular Angular 测试 - 如何在 angular 测试中模拟 document.getElementbyId? - Angular test - how to mock document.getElementbyId in angular test? typescript子组件document.getElementById返回null - typescript child component document.getElementById return null 带有 Nrwl/Nx 的 Angular SSR - 外部库调用 document.getElementById - Angular SSR with Nrwl/Nx - external library calls document.getElementById 无法使用 document.getelementById(id) 将焦点设置在 angular 编辑器上 - Unable to set focus on angular editor using document.getelementById(id) 打字稿中是否有“document.getElementById(&#39;first&#39;)”的替代方案? - Is there any alternative of `document.getElementById('first')` in typescript? 如何通过 document.getElementById inAngular 更改显示 - How to change display by document.getElementById inAngular
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM