Search code examples
angulartypescriptsubject

Can't get updated value from service variable


I'm trying to apply a filter to search items based on a service variable which is updated with an input from that service. But I'm just getting the initial value from the service in my component

Service HTML (whatever I type in is assigned to the variable searchInput correctly):

<input [value]="searchInput" (keyup)="searchInputChange.next(searchFilterService.applyFilter($event.target.value))">

Service TS (it's called component since I already have a service with the same name atm):

export class SearchFilterComponent {

    searchInput: string = 'test';
    searchInputChange: Subject<string> = new Subject<string>();

    constructor(
        public searchFilterService: SharedSearchFilterService) {
        this.searchInputChange.subscribe((value) => {
            this.searchInput = value
        });
    }

    getSearchInput(): string {
        return this.searchInput;
    }
}

Filter Service TS:

@Injectable()
export class SharedSearchFilterService {
    
    applyFilter(filterValue: string) {

        if (filterValue) return filterValue;
        else return ''; // I need this to avoid getting 'undefined'
    }
}

Component HTML (here I'm getting the initial value which is 'test', then it never gets the new value from the service):

<ng-container *ngIf="searchFilterService.licenceFilter(item, service.getSearchInput())">

Link to an example: https://stackblitz.com/edit/angular-buagfs


Solution

  • The AppService in your sample is a component. You have to use @Output to notify value.

    app.service.ts

    @Component({
      selector: 'search-component',
      template: `
        <div fxLayout="row" fxLayoutAlign="space-between center">
          <input
            [(ngModel)]="searchInput"
            (keyup)="onKeyUp()"
          />
        </div>
      `
    })
    export class AppService implements OnInit {
      searchInput: string = 'test';
      @Output() inputValue = new EventEmitter<string>();
    
      constructor() {
      }
    
      ngOnInit() {
        this.inputValue.emit(this.searchInput);
      }
    
      onKeyUp(): void {
        this.inputValue.emit(this.searchInput);
      }
    
      getSearchInput(): string {
        return this.searchInput;
      }
    }
    

    app.component.html

    <hello name="{{ name }}"></hello>
    <search-component (inputValue)="onInputValueEmitted($event)"></search-component>
    <div *ngIf="searchInput == 'test'">This shouldn't be seen if value is not 'test'</div>
    

    app.component.ts

    import { Component, OnInit } from '@angular/core';
    import { AppService } from './app.service';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
      name = 'Angular';
      searchInput = '';
    
      constructor(private service: AppService) {}
    
      onInputValueEmitted(value: string) {
        this.searchInput = value;
      }
    }
    

    Stackblitz sample