'BehaviorSubject in angular returning null null

I am using BehaviorSubject to store some form data info, but for some reason, the info returned by BehaviorSubject is null. myService.ts

 taskData$: BehaviorSubject<any> = new BehaviorSubject({});
task.create.component.html which uses a custom library

<sc-form-wrapper>
            <div class="button-wrap">
                <div class="input-text-container">                   
                    <sc-text-input id="taskName" (onFocusout)="getTaskName($event)"
                                    [required]="true"                                    
                                    label="Task Name"
                                    size="md">
                    </sc-text-input>                   
                </div>
            </div>
            <div class="">Task Colors</div>
            <div *ngFor="let code of taskdata; let i = index" class="radio-container">
                <ng-container>
                    <div class="radio-task-list">
                        <input id="{{ 'radio-' + i }}" class="radio-custom" name="radio-group" type="radio" (change)="selectTaskCode($event,code)">
                        <label for="{{ 'radio-' + i }}" class="radio-custom-label tag-color-{{i}}"></label>
                    </div>
                </ng-container>
            </div>
        </sc-form-wrapper>

task.create.component.ts

import { Component, OnInit, Renderer2 } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { SetTask } from '../../models/task.model';
import { TaskSetCode } from '../../models/task-set-code.model';
import { ErrorHandlerService } from '../../services/error-handler.service';
import { TaskListService } from '../../services/task-list.service';

@Component({
  selector: 'app-task-create',
  templateUrl: './task-create.component.html',
  styleUrls: ['./task-create.component.css']
})
export class TaskCreateComponent implements OnInit {
    private destroy$: Subject<boolean> = new Subject<boolean>();  
    setTask: SetTask;
    selectedTaskName: any;
    selectedTaskCode: any;
    setTaskData: any;    
    disableCreateButton: boolean = true;
    taskSetCode: TaskSetCode = new TaskSetCode();
    selectedTaskData: any;


    constructor(   
        private errorHandlerService: ErrorHandlerService,
        private taskService: TaskListService,
        private router: Router,
        private activeRoute: ActivatedRoute,
        private renderer: Renderer2
    ) { }

    ngOnInit(): void {
        this.setTask = {
            taskName: "",
            taskCode: "",
            createdBy: ""
        };
       this.createButtonDisable();
    }

    ngOnDestroy(): void {
        this.destroy$.next(true);
        this.destroy$.complete();        
    }


    //Getting the task name
    getTaskName(event) {
        Object.defineProperty(this.setTask, event.controlName, { value: event.value });
        this.selectedTaskName = this.setTask.taskName;
        if (event.controlName === "taskName" && event.value !== undefined)  {
            this.disableCreateButton = false;
        } else {
            this.disableCreateButton = true;
        }
        this.createButtonDisable();
        const setTaskData: SetTag = {
            taskName: this.selectedTaskTaskName,
            taskCode: this.selectedTaskCode,
        };   
       this.createButtonDisable();
    }

    //Getting the selected task code
    selectTaskCode(e, Code: string) {
        this.selectedTaskCode = code;
        const setTaskData: SetTag = {
            taskName: this.selectedTaskTaskName,
            taskCode: this.selectedTaskCode,
        };
        this.setTaskData = setTaskData;
        if (this.selectedTaskCode == '' && this.selectedTaskName == '' ) {
            this.disableCreateButton = true;
        } else {
            this.disableCreateButton = false;
        }
        this.createButtonDisable();
               
    }

    
    createButtonDisable() {           
        if (this.setTaskData !== undefined) {          
            this.taskService.taskData$.next(this.setTaskData);
        }
    }

 }

Trying to subscribe the data in task-list.component and trying to get the data, but getting null value

import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { TaskListService } from '../../services/task-list.service';
import { TaskCreateComponent } from '../task-create/task-create.component';
import { ModalService } from 'model-components';

@Component({
  selector: 'app-task-list',
  templateUrl: './task-list.component.html',
  styleUrls: ['./task-list.component.css']
})
export class TaskListComponent implements OnInit {    
    private destroy$: Subject<boolean> = new Subject();

    taskData: any;

    constructor(
        public taskService: TaskListService       
    ) { }

    ngOnInit(): void {   
       
    }

    ngOnDestroy(): void {
        this.destroy$.next(true);
        this.destroy$.unsubscribe();
    }
    createTask(): void {

        const ref = this.modalService.openModal('Create Task', TaskCreateComponent,
            {                
                cancelText: 'Cancel',
                submitText: 'Create'

            }
        );

        const modalCompInstance: any = ref.componentInstance;
        modalCompInstance.modalEvent.subscribe((event) => {
            const type = event.type;

            if (type !== 'submit') {
                ref.close();
                return;
            }
            else {
                this.saveTag();                
                ref.close();
            }
        });
    }

    saveTask() {
        
        this.taskService.taskData$.pipe(takeUntil(this.destroy$))
            .subscribe((tasks: any) => {                
                this.taskData = tasks;
            });
    }
}

Can you please point out the issue or guide me?



Solution 1:[1]

You need to call your saveTask in your ngOnInit lifecycle hook within your TaskListComponent

ngOnInit() {
 this.saveTask();
}

ngOnInit will listen for any changes emitted by your special observable taskData$

Also, it is a good practice to have functions within your service to handle your subject, you want only your service nexting the values, with this approach, it is also easier for testing purposes

export class YourService {
  private theSubject = new BehaviorSubject({});

  getTasks(): Observable<any> {
    return this.theSubject.asObservable();
  }

  nextMyValue(value: any): void {
    this.theSubject.next(value);
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1