在组件< =>之间绑定数据Angular2 ui-router。父州< =>孩子的状态

时间:2017-03-03 00:48:11

标签: angular angular-ui-router angular-material2

这是我要做的事情的要点。我有一个带有Dark / Light主题的标题组件,用于Angular2 Material。标题组件位于“主”状态内。我有一个嵌套的< ui-view>标签,我的main.home和其他main.child状态将存在。当我切换isDarkTheme时,main得到它,[class.mg2-darkTheme] =“isDarkTheme”切换工作,但是生活在主要的孩子们。不要,他们的主题不会改变。

/ *如果有另一种方法,我会很高兴听到它,但我一直在尝试使用我的AngularJS1.x技能,试图在父母和孩子之间双向绑定数据,至今尚未成功...... * /

在AngularJS1.x和ui-router中传递数据非常直观。只需解析一个对象,甚至更好,获取$ scope。$ parent.main,你就可以访问子路由上的整个父对象,双向绑定。 Angular2和ui-router有点挑战性。

我在ui-router https://ui-router.github.io/ng2/上找到的文档只是指向路由参数。但我没有导航到:id。我只想在父< =>之间绑定数据child(只是一个简单的布尔切换)。

我正在尝试将数据(... isDarkTheme的布尔值)从父“main”状态的组件“header-menu”传递给父“main”本身,然后传递到子状态' main.home”。

'main.component'有一个isDarkTheme布尔值,它是'header-menu.component'的@Input,在那里切换,然后回到main。

头-menu.component.ts:

SELECT
    calls.Id,
    calls.DateBegin,
    calls.DateEnd,
    calls.Phone,
    contacts.Name
FROM
    calls LEFT JOIN contacts ON
        RIGHT(calls.Number, 8) = RIGHT(contacts.Phone1, 8) OR
        RIGHT(calls.Number, 8) = RIGHT(contacts.Phone2, 8)
WHERE
    calls.UserId = 1 AND contacts.UserId = 1 
GROUP BY
    calls.Id
ORDER BY
    calls.DateBegin DESC;

头-menu.component.html:

import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
    selector: 'header-menu',
    templateUrl: './header-menu.component.html',
    styleUrls: ['../shared/material-theme.scss', './header-menu.component.scss']
})
export class HeaderMenuComponent {
    // this is set in main and passed in as attr in main.html
    @Input() headerIsDarkTheme: boolean;
    // guessing I pass this bool back out with emitter...
    @Output() themeOnClicked = new EventEmitter<boolean>;
    notifyParentTheme(): void {
        this.headerIsDarkTheme = !this.headerIsDarkTheme;
        this.notifyParentTheme.emit(this.headerIsDarkTheme);
    }
}

main.component.ts:

<div [class.mg2-darkTheme]='headerIsDarkTheme'>..</div>
<button (click)="notifyParentTheme()"

main.component.html:

import { Component, OnInit } from '@angular/core';
@Component({
    selector: 'main-cmp', 
    templateUrl: './main.component.ts',
    styleUrls: ['../shared/material-theme.scss']
})
export class MainComponent implements OnInit { 
    isDarkTheme: boolean;

    NgOnInit(){
        // initializing here... perhaps a better place to init...
        this.isDarkTheme = false;
    }
    listenForTheme( isDarkTheme: boolean ): void {
        this.isDarkTheme = isDarkTheme;

    /****************************************
    *   MAIN QUESTION
    *  How do I pass this theme down to the main.home state?
    *  
    ****************************************/    
    }
}

main.home.component.html:

<div [class.mg2-darkTheme]="isDarkTheme">

  <!-- pass in isDarktheme from 'main' into header-menu, header receives with headerIsDarkTheme -->
  <!-- receive toggled theme from header-menu, event (notifyParentTheme) gets the event, then sends to method processHeaderTheme( $event ) -->
  <header-menu [ headerIsDarkTheme ]="isDarkTheme"
              ( themeOnClicked )="listenForTheme( $event )">
  </header-menu>

  <!-- I want to pass this into the ui-view to toggle the theme -->
  <!-- WHY? because the Angular2 Material theme doesn't work in ui-view -->
  <!-- But darkThem works just using a component like <home-cmp></home-cmp> -->
  <ui-view></ui-view>
</div>

main.home.component.ts

<div [class.mg2-darkTheme]="homeIsDarkTheme">...</div>

states.ts

import { Component, Input } from '@angular/core';
@Component({
    selector: 'home-cmp',
    templateUrl: './home.component.html'
})
export class HomeComponent { 
    @Input() homeIsDarkTheme: boolean;
}

router.config.ts

...
export const mainState = { 
  name: 'main',
  // url: '/main',
  component: MainComponent
}; 
export const homeState = { 
    name: 'main.home',
    url: '/home',
    component: HomeComponent
}; 

app.module.ts     ....     const INITIAL_STATES = [         mainState,         老家     ];

import {UIRouter} from "ui-router-ng2";
import {Injector, Injectable} from "@angular/core";

 /** UIRouter Config  */
export function uiRouterConfigFn(router: UIRouter, injector: Injector) {
    // If no URL matches, go to the `hello` state by default
    router.urlService.rules.otherwise({ state: 'main' });
}

1 个答案:

答案 0 :(得分:-1)

好的,如果我明白你要做什么: MainComponent提供初始isDarkTheme并监听HeaderMenuComponent以进行更改

//MainComponent html
 <header-menu [ headerIsDarkTheme ]="isDarkTheme"
              ( themeOnClicked )="listenForTheme( $event )">
  </header-menu>

//MainComponent
isDarkTheme: boolean = false; //you can initialize isDarkTheme here

listenForTheme( isDarkTheme: boolean ): void {
        this.isDarkTheme = isDarkTheme; 
    }

HeaderMenuComponent获取headerIsDarkTheme并通知main进行任何更改:

//HeaderMenuComponent html
<button (click)="notifyParentTheme()">Notify Parent</button>

//HeaderMenuComponent
@Input() headerIsDarkTheme: boolean;

@Output() themeOnClicked = new EventEmitter<boolean>; //you'll emit a boolean not a type headerIsDarkTheme
notifyParentTheme(): void {
        this.headerIsDarkTheme = !this.headerIsDarkTheme;
        this.themeOnClicked.emit(this.headerIsDarkTheme); //change notifyParentTheme to themeOnClicked
    }

编辑:所以你的主要问题是如何将headerIsDarkTheme传递给HomeComponent。

//HomeComponent html
<div [class.mg2-darkTheme]="homeIsDarkTheme">...</div>

您似乎没有HomeComponent和MainComponent之间的直接交互,因此HomeComponent中的输入无用

export class HomeComponent { 
    @Input() homeIsDarkTheme: boolean;//you can't get your theme with this input
}

我建议您create a service。你的代码有点乱(没有冒犯),创建服务会更具可读性。

也就是说,如果你想坚持输入和输出,在Home和Main之间创建一个直接关系,并从Main发出值。就像是:

所以你这里不需要任何路由器...如果这个答案不能按你的意愿工作,我强烈建议你提供一个探索者