简体   繁体   中英

How can I load content into another component with on click event? (Angular 4)

I have the following problem:

in the sidebar is my menu and I would like if I click on the button kag three new buttons in the component header are loaded (see pic).

I do not know how I can implement it :( Can you give me a tip or example? I realize that this is done with event binding, but how to spend content with a click in another component, I do not know yet. ..

Best regards Andreas

Here is my Dashboard

There are several available options to solve your problem. For the solution I'll provide, I'm assuming that your right menu and head menus have been both put in your root component.

What I would do is using a resolver which will be linked to your route. This resolver will then update your menu. This implies that your menu has been stored either in a service or in an app state with ngrx. Lets forget ngrx for the moment and lets assume you are using a plain angular service.

By storing your menu's items configuration within a service, you totally detached the control of it from other component. It makes the behavior easier to unit test. It also provides flexibility as your menu can be configured differently without changing an already implemented behavior.

Here is a suggested implementation. I have not tested it but it might bring you a starting path:

Here is the service

export type MenuItems = MenuItem[];

export interface MenuItem {
    label: string;
}

@Injectable()
export class MenuItemsService {

     private $menuItems = new BehaviorSubject([]);

     set menuItems(menuItems: MenuItems){
         this.$menuItems.next(menuItems);
     }

     get menuItemsChanges() {
         return this.$menuItems;
     }
}

Here is the resolver. Don't forget to link it to your route in order to make it executed. Of course, if you want to do it from any other location than a Resolver, then you can call your MenuItemsService the same way.

@Injectable()
export class KAGDetailsResolve implements Resolve<MenuItems[]> {

    menuItems: MenuItems = [
        {
            label: 'My first button'
        },
        {
            label: 'My second button'
        },
    ];

    constructor(private menuItemService: MenuItemsService) {}

    resolve(route: ActivatedRouteSnapshot) {

        this.menuItemService.menuItems = this.menuItems;

        return this.menuItems; // we return it as it is mandatory but that's actually not used in this example
    }
}

And here is the component which will be responsible for displaying the dynamic menu:

// the  component which will render your menu
@Component({
    selector: 'my-dynamic-menu',
    template: `<ul>
                <li *ngFor="menuItem in menuItems | async"> {{ menuItem.label }}</li>
               </ul>`
})
export class MyDynamicMenuComponent implements OnInit{

    $menuItems: Observable<MenuItems>;

    constructor(private menuItemService: MenuItemsService) {}

    ngOnInit(): void {
        this.$menuItems = this.menuItemService.menuItemsChanges;
    }
}

As you can see, it relies on Observable . Moreover, the MenuItem class is very poor but allows you to describes more properties on your item (color, css class, function to trigger on click, any url, etc)

You can create a shortcut component. How it will work ?

  • take a list of selected menu, from the menu-component
  • when the user (click) send an update in a shared BehaviorSubject/Observable you can add into your main services
  • add to each of your component this service in the constructor


// in both component
constructor(private mainService: MainService) {}
// on click on your li or a
mainService.shortcut.next(['menu1')); 


// in your menu component, onInit : 

this.mainService.shortcut.subscribe((shortcut) => {
   if(shortcut) { this.shortcutList.push(shortcut); }
};

If your component is pretty straight-forward then you can use the following code snippet.

app.component.html

<p>
    <button (click)="btnClickHandler()">KAG Details</button>
</p>
<app-main-header [showHeaderButtons]="showMainHeaderButtons"></app-main-header>

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  showMainHeaderButtons: boolean = false;
  btnClickHandler() {
    this.showMainHeaderButtons = !this.showMainHeaderButtons;
  }
}

main-header.component.html

<ng-container *ngIf="showHeaderButtons">
  <button>Sample Button 1</button>
  <button>Sample Button 2</button>
  <button>Sample Button 3</button>
</ng-container>

main-header.component.ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-main-header',
  templateUrl: './main-header.component.html',
  styleUrls: ['./main-header.component.css']
})
export class MainHeaderComponent {
  private showHeaderButtons: boolean = false;

  @Input('showHeaderButtons')
  set setData(value: boolean) {
    this.showHeaderButtons = value;
  }
}

The other approach for solving your issue is to use observable which is answered by @Grégory Elhaimer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM