Monaca Onsen UI Discord Chat Github Repo

Datahandling between Components. OnsToolbar and OnsNavigator



  • Hello together :)

    I’m new to OnsenUI and currently I’m struggeling with some problems regarding datahandling between components using the OnsToolbar.

    My project is set up with Angular 11 and I’ve included OnsenUI (otherwise I wouldn’t have posted my question here :D).

    In my app.component I’m handling the navigation with an OnsToolbar:

    <ons-page>
      <ons-toolbar>
        <div class="center">
          <ons-segment id="segment" tabbar-id="tabbar" style="width: 50%">
            <button>Liste</button>
            <button>Radar</button>
            <button>Favoriten</button>
          </ons-segment>
        </div>
      </ons-toolbar>
    
      <ons-tabbar id="tabbar">
        <ons-tab [page]="listTab" active></ons-tab>
        <ons-tab [page]="radarTab"></ons-tab>
        <ons-tab [page]="favTab"></ons-tab>
      </ons-tabbar>
    </ons-page>
    

    Switching between the components works fine and looks good. Now I’ve got the problem, that I want to load data in the listTab-component and change the values of some entries (isFavourite true or false).

    Those changes should affect the values which are displayed in the favTab-component. My problem ist, that when the App starts, the values are load in the listTab-component and I switch the values of some entries to favourite and vice versa.
    But only the initial result (without the changes) is displayed in the favTab-component when I navigate there by using the OnsToolbar… The changes made on the listTab don’t affect the entries displayed in the favTab.

    My last attemp was to integrate the OnsNavigator. But when I’m trying to access it in the listTab-component contructor the page is empty. Without the navigator the content is normally displayed. I wanted to handle it in this way:

    this.navigator.element.pushPage(SecondPageComponent, {data: {foo: 1234}});
    

    Now I’m struggeling how to continue. Maybe you can help me if I’m handling the process correctly at all and just a small step is missing or am I on the absolute wrong path?
    Maybe there is an eventhandler which recognises when a tab is switched in the OnsToolbar?

    Here is the code of my listTab-component:

    .js:

    import {Component, OnInit} from '@angular/core';
    import {PoiHelperService} from "../../services/poiService/poi-helper.service";
    import {POI} from "../../objects/POI";
    
    @Component({
      selector: 'ons-page[list]', // Selector muss ons-page sein da sons die Tabbar nicht funktioniert
      templateUrl: './list-tab.component.html',
      styleUrls: ['./list-tab.component.css']
    })
    export class ListTabComponent implements OnInit {
    
      poiList: POI[] = [];
    
      constructor(private poiHelperService: PoiHelperService) {
      }
    
      push() {
        // Push SecontPageComponent to `ons-navigator
      }
    
      ngOnInit(): void {
        this.getPOIList();
      }
    
      getPOIList(): void {
        this.poiHelperService.getPOIList()
          .subscribe(poiList => this.poiList = poiList);
      }
    
      changeFavStatus(poi: POI): void {
        poi.isFavourite = !poi.isFavourite;
    
        this.poiHelperService.updatePOI(poi)
          .subscribe();
      }
    
      searchForPOI(input: string): void {
        this.poiHelperService.searchPOIs(input)
          .subscribe(poiList => this.poiList = poiList);
      }
    
    }
    
    

    .html:

    <ons-list modifier="inset" style="margin-top: 10px">
      <ons-list-header style="text-align: center">POI's in deiner Nähe</ons-list-header>
    
      <p style="text-align: center; margin-top: 10px;">
        <ons-search-input style="width: 50%"
                          placeholder="Search"
                          onchange="searchForPOI(this.value)"
        ></ons-search-input>
      </p>
    
      <table style="width: 100%; border:0">
        <tr>
          <ons-list-item *ngFor="let poi of poiList;" style="margin-top: 5px">
            <td width="20%" class="left">
              <img class="list-item__thumbnail" [src]="poi.thumbnail" style="margin: auto;">
            </td>
            <td width="65%" class="center">
              <span class="list-item__title">{{poi.name}}</span>
              <span class="list-item__subtitle">{{poi.description}}</span>
            </td>
            <td width="15%" class="right">
              <ons-button modifier="quiet" (click)="changeFavStatus(poi)" style="margin: auto;">
                <i *ngIf="poi.isFavourite" class="fas fa-heart" style="color: darkred;"></i>
                <i *ngIf="!poi.isFavourite" class="far fa-heart" style="color: darkred;"></i>
              </ons-button>
            </td>
          </ons-list-item>
        </tr>
      </table>
    </ons-list>
    
    <br/>
    
    

    Here is the code of my favTab-component:

    .js:

    import {Component, OnInit} from '@angular/core';
    import {PoiHelperService} from "../../services/poiService/poi-helper.service";
    import {POI} from "../../objects/POI";
    import {MatTableDataSource} from "@angular/material/table";
    
    @Component({
      selector: 'ons-page[fav]', // Selector muss ons-page sein da sons die Tabbar nicht funktioniert
      templateUrl: './fav-tab.component.html',
      styleUrls: ['./fav-tab.component.css']
    })
    export class FavTabComponent implements OnInit {
    
      displayedColumns: string[] = ['thumbnail', 'name'];
    
      leftDisplayedDatasource = new MatTableDataSource<POI>();
      rightDisplayedDataSource = new MatTableDataSource<POI>();
    
      constructor(private poiHelperService: PoiHelperService) {
      }
    
      ngOnInit(): void {
        this.getFavPOIList();
      }
    
      getFavPOIList(): void {
        this.poiHelperService.getFavouritePOIs()
          .subscribe(favPoiList => this.defineDisplayDataSources(favPoiList));
      }
    
      defineDisplayDataSources(favPoiList: POI[]) {
    
        let half = Math.ceil(favPoiList.length / 2);
        this.leftDisplayedDatasource = new MatTableDataSource(favPoiList.splice(0, half));
        this.rightDisplayedDataSource = new MatTableDataSource(favPoiList.splice(-half));
      }
    
    }
    
    

    .html:

    <ons-list modifier="inset" style="margin-top: 10px">
      <ons-list-header style="text-align: center">Deine POI-Favoriten</ons-list-header>
    
      <table mat-table [dataSource]="leftDisplayedDatasource" class="mat-elevation-z8">
    
        <ng-container matColumnDef="thumbnail">
          <th mat-header-cell *matHeaderCellDef></th>
          <td mat-cell [ngClass]="'mat-cell-left-data'" *matCellDef="let element">
            <img class="list-item__thumbnail" [src]="element.thumbnail" style="margin: auto;">
          </td>
        </ng-container>
    
        <ng-container matColumnDef="name">
          <th mat-header-cell class="ToBeApplied" *matHeaderCellDef></th>
          <td mat-cell [ngClass]="'mat-cell-right-data'" *matCellDef="let element">{{element.name}}</td>
        </ng-container>
    
        <tr mat-header-row *matHeaderRowDef="displayedColumns" style="display: none"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
      </table>
    
      <table mat-table [dataSource]="rightDisplayedDataSource" class="mat-elevation-z8">
    
        <ng-container matColumnDef="thumbnail">
          <th mat-header-cell *matHeaderCellDef></th>
          <td mat-cell [ngClass]="'mat-cell-left-data'" *matCellDef="let element">
            <img class="list-item__thumbnail" [src]="element.thumbnail" style="margin: auto;">
          </td>
        </ng-container>
    
        <ng-container matColumnDef="name">
          <th mat-header-cell *matHeaderCellDef></th>
          <td mat-cell [ngClass]="'mat-cell-right-data'" *matCellDef="let element">{{element.name}}</td>
        </ng-container>
    
        <tr mat-header-row *matHeaderRowDef="displayedColumns" style="display: none"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
      </table>
    
    </ons-list>
    
    <br/>
    
    

    It’s not the best code but currently I just want to get it working. The refactoring or code-style is planned afterwards :)

    Thx for Input and your help!
    Kind regards
    Martin