• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Angular przekazywanie zmiennej

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
912 wizyt
pytanie zadane 19 marca 2020 w JavaScript przez michal_php Stary wyjadacz (13,700 p.)

Cześć.

Prubuje przekazać zmienna z componentu rodzica do dziecka ,ale nie wiem co robię źle ,że component dziecko jej nie widzi: ( komentarzami opisałem z kąt do kąt wysyłam zmienną)

component rodzic:

import { Component, OnInit } from '@angular/core';
import {AuthenticationService} from '../../../_services/authentication.service';
import {Router} from '@angular/router';
import {UserService} from '../../../_services/user.service';
import {CalendarService} from '../../../_services/calendar.service';
import {first} from 'rxjs/operators';
import {Calendar} from '../../../_model/calendar';
import {ValueService} from '../../value.service';

@Component({
  selector: 'app-calendar',
  templateUrl: './calendar.component.html',
  styleUrls: ['./calendar.component.less']
})
export class CalendarComponent implements OnInit {
  actualDay: number;
  monthNumber: number;
  month: string;
  year: number;
  allDays: Calendar[];
  start: Calendar[];
  load = true;

  constructor(
    private calendarService: CalendarService,
    private router: Router,
    private valueService: ValueService
  ) {
    const data = new Date();
    this.actualDay = data.getDate();
    this.monthNumber = data.getMonth() + 1;
    this.year = data.getFullYear();
  }

  ngOnInit(): void {
    this.getAllDays();
  }

  getAllDays() {
    this.calendarService.getNumberDays().pipe(first()).subscribe(days => {
        this.allDays = days;
    })
  }


  // tutaj przekazuje liczbę i z tond przekazuje ją da service
 // metoda getNexDay jest uruchomiana poprzez klikniecie button z odpowiadaniom wartością
  getNexDay(day : number) { 
    this.valueService.nextDay(day);
  }

}

service:

import { Injectable } from '@angular/core';
import {Subject} from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ValueService {

  dayNext$ = new Subject<number>();

  nextDay(day : number) {
    this.dayNext$.next(day);
    console.log(day); // tutaj działa i widzi tą zmienna
  }
}

i component dziecko:

import { Component, OnInit } from '@angular/core';
import {CalendarService} from '../../../../_services/calendar.service';
import {first} from 'rxjs/operators';
import {Task} from '../../../../_model/task';
import {ValueService} from '../../../value.service';
import {Subscription} from 'rxjs/';

@Component({
  selector: 'app-task',
  templateUrl: './task.component.html',
  styleUrls: ['./task.component.less']
})
export class TaskComponent implements OnInit {
  tasks: Task[];
  nextDay: Subscription;
  findNexDay: number;

  constructor(
    private calendarService: CalendarService,
    private valueService: ValueService
  ) { }

  ngOnInit(): void {
    this.getTasks();
  }

  getTasks() {
    this.calendarService.getTasks().pipe(first()).subscribe(task=>{
      this.tasks = task;
    })
  }

 // tutaj staram się pobrać zmienną ale nic nie widzi
  getNextTask() {
      this.nextDay = this.valueService.dayNext$.subscribe((day)=>{
      this.findNexDay = day;
    })
console.log(this.findNexDay); // tutaj już właśnie nie widzi i nie chce poprać zmiennej
  }

}

Z góry bardzo dziękuje za pomoc lub wskazówkę.

1 odpowiedź

+2 głosów
odpowiedź 19 marca 2020 przez Aisekai Nałogowiec (42,190 p.)
edycja 19 marca 2020 przez Aisekai
  getNextTask() {
      this.nextDay = this.valueService.dayNext$.subscribe((day)=>{
      this.findNexDay = day;
    })
console.log(this.findNexDay); // tutaj już właśnie nie widzi i nie chce poprać zmiennej
  }
}

Bo subscribe działa asynchronicznie, a JS jest językiem jednowątkowym. Więc odwołać się do tej zmiennej, powinieneś wewnątrz callbacku subscribe.  Podobna sytuacja jest gdy robisz sobie np. setTimeout(()=>{}, 0), wtedy mimo że timeout jest równy 0, to i tak to się wywoła dopiero w chwili "gdy nic innego się nie będzie robiło".

Dwa, ta metoda jest zrypana trochę, bo subscribe'ujesz za każdym razem gdy ją wywolujesz. I o ile takie coś działa (i jest konieczne) podczas pobierania danych z serwera (żądanie-odpowiedź), o  tyle teraz za każdym razem gdy wywołujesz tą funkcję, tworzysz nowy callback. Po pierwsze, nie unsubscribe'ujesz tego, po drugie masz memory leak. 

komentarz 19 marca 2020 przez michal_php Stary wyjadacz (13,700 p.)
A jak byś polecał to zrobić ?
komentarz 19 marca 2020 przez Aisekai Nałogowiec (42,190 p.)
A co chcesz osiągnąć?
komentarz 19 marca 2020 przez michal_php Stary wyjadacz (13,700 p.)
Chce przekazać tylko zmienną z rodzica do dziecka. A czy można by coś zrobić aby ta moja metoda była poprawna ?
komentarz 19 marca 2020 przez michal_php Stary wyjadacz (13,700 p.)

Zrobiłem coś takiego. Ale jak mam zrobić tego callback ?

Dodałem unsubscribe. Czy teraz było by lepiej ?

import { Component, OnInit, OnDestroy } from '@angular/core';
import {CalendarService} from '../../../../_services/calendar.service';
import {first} from 'rxjs/operators';
import {Task} from '../../../../_model/task';
import {ValueService} from '../../../value.service';
import {Subscription} from 'rxjs/';

@Component({
  selector: 'app-task',
  templateUrl: './task.component.html',
  styleUrls: ['./task.component.less']
})
export class TaskComponent implements OnInit, OnDestroy {
  tasks: Task[];
  nextDay: Subscription;
  findNexDay: number;

  constructor(
    private calendarService: CalendarService,
    private valueService: ValueService
  ) { }

  ngOnInit(): void {
    this.getNextTask();
  }

  getNextTask() {  // nie za bardzo wiem jak zrobić tego callback
     this.nextDay = this.valueService.dayNext$.subscribe((task)=>{
       this.findNexDay = task;
     })
    console.log(this.nextDay);
  }

  ngOnDestroy(): void { // to dodałem 
    if (this.nextDay){
        this.nextDay.unsubscribe();
    }
  }

}

 

komentarz 19 marca 2020 przez Aisekai Nałogowiec (42,190 p.)

Dobra. Zacznijmy od tego. Callback, to jest funkcja którą podsyłasz, która ma zostać wywołana w "pewnej chwili" (nie wywołujesz jej od razu, tylko w twoim przypadku, subject przechowuje sobie wszystkie funkcje i w chwili gdy używasz next, wywołuje je jako parametr podając wartość którą przekażesz w next). 

I teraz tak. Masz kilka opcji do komunikacji między komponentami. Jedną z nich jest @Input i @Output. Drugą jest to co teraz masz, czyli przez serwis. Ja bym to zrobił tak, że w ngOnInit, wywołałbym funkcję taką:

 getNextTask() {  // nie za bardzo wiem jak zrobić tego callback
     return this.nextDay = this.valueService.dayNext$.subscribe((task)=>{
       this.findNexDay = task;
     })
  }

Jako pole w klasie dodałbym:

subscriptions = new Subscription()

W ngOnInit:

this.subscriptions.add(this.getTasks());

W ngOnDestroy:

this,subscriptions.unsubscribe();

I teraz gdy chcesz "przekazać" wartość między komponentami, to np jak masz inny komponent który ma przycisk: "Następne zadania", to podpinasz do niego zachowanie które spowoduje, że w serwisie zostanie wywołana metoda .next() z nowymi Taskami (Task[]). 

I teraz tak:

gdy masz metodę valueService.dayNext$.subscribe(), to tak jak wcześniej podałem, jako parametr podajesz funkcję która ma zostać wywołana. A jako parametr, dostaniesz taki typ i taką wartość, jaka np zostanie przesłana do subject.

Podobne pytania

0 głosów
1 odpowiedź 150 wizyt
pytanie zadane 15 marca 2020 w JavaScript przez michal_php Stary wyjadacz (13,700 p.)
0 głosów
0 odpowiedzi 119 wizyt
pytanie zadane 7 kwietnia 2018 w JavaScript przez pulson666 Stary wyjadacz (12,560 p.)
0 głosów
1 odpowiedź 230 wizyt
pytanie zadane 18 maja 2017 w JavaScript przez crova Użytkownik (940 p.)

93,191 zapytań

142,206 odpowiedzi

322,042 komentarzy

62,518 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 3053p. - dia-Chann
  2. 2998p. - Łukasz Piwowar
  3. 2993p. - Łukasz Eckert
  4. 2970p. - CC PL
  5. 2930p. - Tomasz Bielak
  6. 2907p. - Łukasz Siedlecki
  7. 2890p. - rucin93
  8. 2584p. - Adrian Wieprzkowicz
  9. 2536p. - Mikbac
  10. 2485p. - Marcin Putra
  11. 2418p. - Michal Drewniak
  12. 2239p. - Michał Telesz
  13. 2156p. - Anonim 3619784
  14. 1733p. - rafalszastok
  15. 1650p. - Mariusz Fornal
Szczegóły i pełne wyniki

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...