简体   繁体   中英

Angular focus on input while clicking an element

I have attached the stackblitz below

https://stackblitz.com/edit/angular-dgx3pe

What i am trying to achieve is while clicking on the label element it should focus on the input.Hence the input:focus class gets activated.What I belive is that it can be achievable through javascript/jquery.But i prefer the angular way to achieve this.

In Brief,these are the two things i am trying to do,

  • Make focus on the input element when label is clicked.
  • When the focus is changed to another input element and if the previous element is not empty(If some value is typed in).The label should maintain its position in the top.

HTML

<input class="input" type="text">
<label class="label">Name</label>

<div>
<input class="input" type="text">
<label class="label">Name</label>
</div>

CSS

p {
  font-family: Lato;
}
.input
{
  border:none;
  border-bottom:1px solid grey;
  outline:none;
   margin-top:20%;
}
.input:focus
{
    border-bottom:1px solid orange;
}
.label
{
  position:relative;
 left:-170px;
}
.input:focus + .label
{
   bottom:20px;
}

You can do this with pure markup. You need to add an id to the input and a for element to the label

<input class="input" type="text" id="firstName">
<label class="label" for="firstName" >First Name</label>

This is just part of the html spec - labels can be associated with inputs - the out of the box functionality here is that on clicking a label it sets focus to its associated input. id and for attributes must match for this to work.

For the second part of your question, and to reuse your css classes - add matching variables to your component. Use ngClass to add the .go-top class when the variable has a value

In component -

firstName: string;

Then in the html -

  <input class="input" type="text" id="firstName" [(ngModel)]="firstName">
  <label class="label" for="firstName" [ngClass]="{'go-top': firstName}">First Name</label>
  1. In the html, add a reference to your input text - #firstNameField and add a method to click event of the label - (click)="focusOnFirstName()"
    <input #firstNameField class="input" type="text">
    <label class="label" (click)="focusOnFirstName()">First Name</label>

  1. In your component declare ViewChild and implement a method to click of label field.
      @ViewChild("firstNameField") firstNameField;

      focusOnFirstName(){
        this.firstNameField.nativeElement.focus();
      }


I'm looking at this from the perspective of making a more "Angular" solution for your conditional style request. To that end, you should focus on rolling your input/label combination into a custom input component. Once you've created a component with your original elements as a starting template you can enact the following more effectively.

Basic strategy is to conditionally apply your styles using Angular's [class] property binding or [NgStyle] directives.

  1. Do a ViewChild query on the template for the input element
    1. Add an event listener on the input element in the template
    2. Whenever a keyup event is detected, it will trigger of check of your <input> field value and update a class property representing whether the field is empty
    3. Change detection will trigger, and the [NgClass] or [class] bindings will trigger updates to the element's class
//component.ts

import { Component, Input, ViewChild, ElementRef } from '@angular/core'

@Component({
  selector: 'app-input',
  styleUrls: ['./input.component.css'],
  templateUrl: './input.component.html'
})

export class InputComponent{
  @Input() labelName: string = "Your Label Here"
  @ViewChild("input") myInput:ElementRef<any> //ViewChild query

  empty: Boolean = true; // this property will track whether input value is truthy

  isEmpty(){ // attached to keyup event on input element in your template file

   if (this.myInput.nativeElement.value){
      this.empty = false;
    } else{
      this.empty = true;
    }
  }

  styles(){ // attached to the [ngClass] directive binding on input element in template file
    return {
      'empty': this.empty ? true: false,
      'not-empty': this.empty ? false: true
    }
  } 

}

//component.html with [ngClass] directive

<label for="my-input" #label> {{ labelName }}
<input type="text" id="my-input" [ngClass]="styles()" (keyup) = "isEmpty()" #input>

//component.html with [style] property binding
// in this instance, empty is a reference to the property in the .ts file

<label for="my-input" #label> {{ labelName }}
<input type="text" id="my-input" [class.empty]="empty" #input>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM