Kurbol
Kurbol

Reputation: 101

Change how content is displayed based on screen size in Angular 4

On a larger screen size I have 3 columns of content. On a smaller screen size I am wanting to display the content in a tab control with 3 tabs.

I have this working using the html below. The problem is that if I make changes to the data a component is bound to it does not update the other copy of the component. So if data is changed while the screen is large, then the screen is made small, it switches to tabs correctly, but the data does not display as updated. The actual data object in code is updated fine.

How can I sync the copied components to always display the same? Basically, when one is changed, the other mimics those changes. Alternatively, is there a different/better way to achieve the same goal of displaying content in tabs when the screen is small.

<div fxHide fxShow.gt-sm >
  <div>
    <h3>Column 1</h3>
    <custom-component1 
      [(data)]="data1">
    </custom-component1>
  </div>
  <div>
    <h3>Column 2</h3>
    <custom-component2 
      [(data)]="data2">
    </custom-component2>
  </div>
  <div>
    <h3>Column 3</h3>
    <custom-component3 
      [(data)]="data3">
    </custom-component3>
  </div>
  
  <mat-tab-group fxShow fxHide.gt-sm>
    <mat-tab label="Column 1">
      <div>
        <h3>Column 1</h3>
        <custom-component1 
          [(data)]="data1">
        </custom-component1>
      </div>
    </mat-tab>
    <mat-tab label="Column 2">
      <div>
        <h3>Column 2</h3>
        <custom-component2 
          [(data)]="data2">
        </custom-component2>
      </div>
    </mat-tab>
    <mat-tab label="Column 3">
      <div>
        <h3>Column 3</h3>
        <custom-component3 
          [(data)]="data3">
        </custom-component3>
      </div>
    </mat-tab>
  </mat-tab-group>
</div>

Upvotes: 1

Views: 11782

Answers (2)

Lorenzo Imperatrice
Lorenzo Imperatrice

Reputation: 997

You have to use an observable of the client window size!

Here is how to do it! Or you can start to use flex-layout for angular, I find this library pretty helpful.

EDIT:

Here is the code for let data observe the screen width size:

your-component.component.ts

import { Component, AfterViewInit } from '@angular/core';
import { ObservableMedia, MediaChange } from '@angular/flex-layout';
import { Subscription } from 'rxjs/Rx';
    
@Component({
  selector: 'app-your-component',
  templateUrl: './your-component.component.html',
  styleUrls: ['./your-component.component.css']
})
export class YourComponentComponent implements AfterViewInit {

  // Subscription of the observer of the screen size
  mediaQuery$: Subscription;

  // The active media query (xs | sm | md | lg | xl)
  activeMediaQuery: string;

  constructor(
    private observableMedia: ObservableMedia
  ) { }

  ngAfterViewInit () {

    this.mediaQuery$ = this.observableMedia.subscribe( (change: MediaChange) => {
      this.activeMediaQuery = `${change.mqAlias}`;
      if (this.activeMediaQuery === 'xs' || this.activeMediaQuery === 'sm') {
        // Here goes code for update data in xs or sm (small screen)
      } else {
        // Here goes code for update data in gt-sm (bigger screen)
      }
    });
  }
}

Upvotes: 8

Kurbol
Kurbol

Reputation: 101

I solved my issue. I found that I was really only having problems keeping radio buttons and check-boxes in sync between the two display types. It turns out there were problems because the radio-button groups were named and it didn't like that there were two groups with the same name.

I didn't need them to be named anyway, so simply removing the names fixed my issue. If you need names I was thinking of adding a GUID to the name that is generated OnInit(). Basically just be careful that you don't have ids and names in your components that have multiple rendered copies because they need to be unique.

Upvotes: 1

Related Questions