最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - get the closest element to a component angular 5 - Stack Overflow

programmeradmin4浏览0评论

I have a text field in an ponent, that when in focus, needs to populate a hidden field outside of the ponent that is nearest to it.

At the moment I can get the field in focus, but what I need to do now is populate the hidden field.

Here is what I have so far:

HTML:

<h2>Test</h2>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>

App-Focus:

<p>
  focus works!
  <input id="inputId" type="text" name="" value="">
</p>

Component:

ngAfterViewInit(){
  setTimeout(()=>{
    let dummyEl = this.elRef.nativeElement.querySelectorAll("#inputId")
    for(let i = 0; i < dummyEl.length; i++){
    let el = dummyEl[i]
    // if (document.activeElement === el){ stops working if I use this
       console.log(document.activeElement === el)
        console.log(el.closest("#h0"))//always returns null

// }
  }
}, 3000)

}

I have a text field in an ponent, that when in focus, needs to populate a hidden field outside of the ponent that is nearest to it.

At the moment I can get the field in focus, but what I need to do now is populate the hidden field.

Here is what I have so far:

HTML:

<h2>Test</h2>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>
<input type="hidden" id="h0" name="" value="">
<app-focus></app-focus>

App-Focus:

<p>
  focus works!
  <input id="inputId" type="text" name="" value="">
</p>

Component:

ngAfterViewInit(){
  setTimeout(()=>{
    let dummyEl = this.elRef.nativeElement.querySelectorAll("#inputId")
    for(let i = 0; i < dummyEl.length; i++){
    let el = dummyEl[i]
    // if (document.activeElement === el){ stops working if I use this
       console.log(document.activeElement === el)
        console.log(el.closest("#h0"))//always returns null

// }
  }
}, 3000)

}
Share Improve this question asked Apr 7, 2018 at 13:58 RasMasonRasMason 2,2125 gold badges36 silver badges60 bronze badges 1
  • Is it just for demonstration reasons or do all your input fields have the same id 'h0'? If so, this could be the reason why the result is null as there is no unique field to return. – user6749601 Commented Apr 7, 2018 at 15:38
Add a ment  | 

2 Answers 2

Reset to default 4

closest searches direct descendants but not siblings of the descendants e.g.

<div>
    <input id="#h0">
    <app-root>
        <p>
            <input id="#inputId">
        </p>
    </app-root>
</div>

In this HTML, calling closest from the #inputId element will only find the div, not the input because it is not a direct descendant - it is a child of div.

You need to modify your html so app-root and #h0 are wrapped by a div. You can then find the closest div and select the child of that element e.g.

ngAfterViewInit() {
    setTimeout(() => {

      let dummyEl = this.elRef.nativeElement.querySelectorAll('#inputId');
      for(let i = 0; i < dummyEl.length; i++) {
        let el = dummyEl[i];

        let div = el.closest('div');
        if(div !== null) {
          console.log(div.querySelector('#h0'));
        }
      }
    }, 3000);
  }
}

Also you id's must be unique so using #h0 for each input is invalid HTML. You might be better using a class if you want to find the elements with the same "tag" e.g.

<input class="h0" ... >

If you need to pass data from the AppFocusComponent, you could use Angular Event Emitters. The example in the documentation emits null in the $event but other data, both primitive and Objects, can be passed as well.

Here is a link to an example on Stack Blitz

app-focus.ponent.ts

First, set up an EventEmitter in the AppFocusComponent. The data can be emitted in an Angular Lifecycle Hook. Or can be bound to a User Input Event.

import { AfterViewInit, Component, EventEmitter, Input, Output } from 

'@angular/core';

@Component({
  selector: 'app-focus',
  templateUrl: './app-focus.ponent.html'
})
export class AppFocusComponent implements AfterViewInit {
  @Input() data: any = null;
  @Output() focus = new EventEmitter();

  ngAfterViewInit() {
    setTimeout(()=>{
      this.focus.emit(this.data);
    }, 3000)
  }

  onFocus(event: Event) {
    console.log(event);
    this.focus.emit(this.data);
  }
}

app-focus.ponent.html

Next, bind the focus event on the input to the onFocus() method in the ponent. Here, ngModel is used to bind the data that is emitted when the onFocus($event) method fires. This can either be from user input, or the data can be passed in via an @Input(). I wasn't sure where the data is ing from, so there a couple of approaches in the example.

<p>
  <input type="text" (focus)="onFocus()" [(ngModel)]="data">
</p>

app.ponent.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.ponent.html',
  styleUrls: [ './app.ponent.css' ]
})
export class AppComponent  {
  h0Value: string = '';
  h1Value: string = '';
  h2Value: string = '';
  h3Value: string = '';

  // an alternate way to set the value instead of setting it in the template
  setH1Value(event: any) {
    this.h1Value = event;
  }
}

app.ponent.html

Lastly, bind the [value] of the <input>s to their respective properties and have the AppComponent listen to the (focus) event from the AppFocusComponent. The data that es from the AppFocusComponent can be assigned directly in the template. (focus)="h0Value = $event". Or it can be wrapped in a method on the ponent while passing the $event through. (focus)="setH1Value($event)". If the data is being initialized via data from an API or some other source, it can be passed in via the @Input. data="h2 data".

The labels here are used for demonstration purposes so the data that's emitted by the AppFocusComponent can be viewed in the UI.

<h2>Test</h2>
<label>{{ h0Value }}</label>
<input type="hidden" id="h0" name="" [value]="h0Value">
<app-focus (focus)="h0Value = $event"></app-focus>

<label>{{ h1Value }}</label>
<input type="hidden" id="h1" name="" [value]="h1Value">
<app-focus (focus)="setH1Value($event)"></app-focus>

<label>{{ h2Value }}</label>
<input type="hidden" id="h2" name="" [value]="h2Value">
<app-focus data="h2 data" (focus)="h2Value = $event"></app-focus>

<label>{{ h3Value }}</label>
<input type="hidden" id="h3" name="" [value]="h3Value">
<app-focus (focus)="h3Value = $event"></app-focus>
发布评论

评论列表(0)

  1. 暂无评论