0

Given are two components: Parent and Child.

parent.ts

class Parent {
    state = 0;
    ...
};

parent.html

<child [state]='state'> </child>

Whenever I update state in Parent, the update is reflected in the child component.

Due to a refactoring, I had to remove state from Parent and instead have now a singleton class:

class Application {
    private static getState();
    private static setState(state: number);
}

Whenever I call Application.setState(0), the child will not be informed anymore. What is a common technique to let the child component know that Application.getState() will now return a different value?

1 Answer 1

1

Best to use Angular BehaviorSubject Service and get the components to subscribe to the change event. I have created a simple Pokemon Api that has exactly what you need. It is very easy to see what is happening in the source code.

The service is as follows

@Injectable()
export class PokemonFilterService {
  private pokemonfilterStatus = new PokemonFilter();
  private pokemonFilterSource = new BehaviorSubject<PokemonFilter>(this.pokemonfilterStatus);

  // this updates the data from the component
  change(data: PokemonFilter) : void {
    this.pokemonFilterSource.next(data);
  }

  // this lets the subscribing component know the data has changed
  public filterDataHasChanged(): Observable<PokemonFilter> {
    return this.pokemonFilterSource.asObservable();
  }
}

The pokemon-header page has this code

@Component({
  selector: 'app-pokemon-header',
  templateUrl: './pokemon-header.component.html',
  styleUrls: ['./pokemon-header.component.scss']
})
export class PokemonHeaderComponent implements OnInit {
  typeList: Array<PokeTypes>;
  pokemonFilter: PokemonFilter;

  constructor(private route: ActivatedRoute, private pokemonFilterService: PokemonFilterService) { }

  ngOnInit(): void {
    // one api call - get the list once and pass it down
    // fyi the api call was cached by the resolver
    this.typeList = this.route.snapshot.data['typeList'].results as Array<PokeTypes>;
    this.typeList = this.typeList.sort((a, b) => (a.name > b.name) ? 1 : -1);
    // use this service to check if the filter values changes from detail component (reset)
    this.pokemonFilterService.filterDataHasChanged().subscribe((pokemonFilter: PokemonFilter) => {
      if (pokemonFilter) {
        this.pokemonFilter = pokemonFilter;
      }
    });
  }

  filterChanged(): void {
    this.pokemonFilterService.change(this.pokemonFilter)
  }
}
  

the pokemon-detail can subscribe and change the data and the header component will be notified.

ngOnInit(): void {
this.pagingOffset = 0;
this.getPokemons(this.pagingOffset);

// use this service to check if the filter values change (reset)
    this.pokemonFilterService.filterDataHasChanged().subscribe((pokemonFilter : PokemonFilter) => {
      if (pokemonFilter) {
        this.pokemonFilter = pokemonFilter;
      }
    });
  }

Summary

In one component you change the data and in the other component, you subscribe to the data. The components can be unrelated.

See full source code here https://github.com/tfa7

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.