内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用
在Angular 2(Beta 6)中,我有一个主菜单的组件。
<mainmenu></mainmenu>
我想将布尔值绑定为宽或窄。因此,我将其转换为:
<mainmenu [(menuvisible)]="true"></mainmenu>
但是我想要的(我认为)是绑定到javascript类属性(因为我可能有其他东西要绑定,但希望通过在组件中使用一个类来保持整洁)。
我有个错误
EXCEPTION: Template parse errors: Invalid property name 'menumodel.visible' ("
][(menumodel.visible)]="menumodel.visible">
如果我对单个变量而不是类进行同样的尝试,就会得到:
Template parse errors: Parser Error: Unexpected token '='
然而,这个(单向绑定?)似乎有效(但我可能希望触发菜单从另一个组件变宽/窄,因此觉得这应该是一个双向数据绑定属性):
<menu [vis]="true"></menu>
这是我的菜单组件的一部分:
@Component({ selector: 'menu', templateUrl: './app/menu.html', providers: [HTTP_PROVIDERS, ApplicationService], directives: [ROUTER_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgForm] }) export class MenuComponent implements OnInit { mainmenu: MainMenuVM; constructor(private _applicationService: ApplicationService) { this.mainmenu = new MainMenuVM(); } // ...ngOnInit, various functions }
这是我的MainMenu视图模型类
export class MainMenuVM { public visible: boolean; constructor( ) { this.visible = true; } }
我正在尝试创建一个菜单,其中包含图标和文本,但可以缩小到只显示图标。我会将此事件向上发送到父组件,以更改菜单旁边容器的位置。触发内容容器最大化将触发菜单缩小--我并不是说这是最好的方法,但我想在深入之前解决这个特定问题。
请注意:我不是在这里对输入控件进行数据绑定-只是将数据绑定到一个组件上,这样我就可以修改UI了。
这是从角度上的小片上来的。
<my-cmp [(title)]="name"> Sets up two-way data binding. Equivalent to: <my-cmp [title]="name" (titleChange)="name=$event">
提前谢了!
更新
将所接受的答案中的代码集成起来,并在这里为我的特定用例调整最后的工作代码:
app.html
...header html content // This is what I started with <!--<menu [menuvisible]="true" (menuvisibleChange)="menuvisible=$event"></menu>--> // This is two way data binding // 1. Banana-in-a-box is the input parameter // 2. Banana-in-a-box is also the output parameter name (Angular appends it's usage with Change in code - to follow shortly) // 3. Banana-in-a-box is the short hand way to declare the commented out code // 4. First parameter (BIAB) refers to the child component, the second refers the variable it will store the result into. // 5. If you just need an input use the remmed out code with just the first attribute / value <menu [(menuvisible)]="menuvisible"></menu> .. div content start <router-outlet></router-outlet> .. div content end
app.Component.ts(根)
export class AppComponent implements OnInit{ menuvisible: Boolean; }
menu.Component.ts(根的子)
export class MenuComponent implements OnInit { // Parameters - notice the appending of "Change" @Input() menuvisible: boolean; @Output() menuvisibleChange: EventEmitter<boolean> = new EventEmitter<boolean>(); // Init ngOnInit() { // Populate menu - fetch application list this.getApplications(); // Initially we want to show/hide the menu depending on the input parameter (this.menuvisible === true) ? this.showMenu() : this.hideMenu(); } //...more code }
menu.html
<div id="menu" [ngClass]="menuStateClass" style="position: absolute; top:0px; left: 0px;z-index: 800; height: 100%; color: #fff; background-color: #282d32"> <div style="margin-top: 35px; padding: 5px 0px 5px 0px;"> <ul class="menuList" style="overflow-x: hidden;"> <li>IsMenuVisible:{{menuvisible}}</li> <li style="border-bottom: 1px solid #3d4247"><a (click)="toggleMenu()"><i class="fa fa-bars menuIcon" style="color: white; font-size: 16px;"></i></a></li> <li *ngFor="#app of applications"> <a [routerLink]="[app.routerLink]"> <i class="menuIcon" [ngClass]="app.icon" [style.color]="app.iconColour" style="color: white;"></i> <span [hidden]="menuStateTextHidden">{{ app.name }}</span> </a> </li> </ul> </div> </div>
记住输入你需要的东西。
从‘angular 2/core’导入{Component,EventEmitter,OnInit,Input,Output};
强烈推荐这段视频到你的管道上:角2教程(2016)-输入和输出
对于双向绑定,您需要如下所示:
@Component({ selector: 'menu', template: ` <button (click)="menuvisible = !menuvisible; menuvisibleChange.emit(menuvisible)">toggle</button> <!-- or <button (click)="toggleVisible()">toggle</button> --> `, // HTTP_PROVIDERS should now be imports: [HttpModule] in @NgModule() providers: [/*HTTP_PROVIDERS*/, ApplicationService], // This should now be added to declarations and imports in @NgModule() // imports: [RouterModule, CommonModule, FormsModule] directives: [/*ROUTER_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgForm*/] }) export class MenuComponent implements OnInit { @Input() menuvisible:boolean; @Output() menuvisibleChange:EventEmitter<boolean> = new EventEmitter<boolean>(); // toggleVisible() { // this.menuvisible = !this.menuvisible; // this.menuvisibleChange.emit(this.menuvisible); // } }
然后用它就像
@Component({ selector: 'some-component', template: ` <menu [(menuvisible)]="menuVisibleInParent"></menu> <div>visible: {{menuVisibleInParent}}</div> ` directives: [MenuComponent] }) class SomeComponent { menuVisibleInParent: boolean; }
至少有两种可能性可以为组件创建双向数据库。
V1:对于像语法这样的ngModel,您必须在@Output属性名称的末尾创建一个具有相同名称行的@Output属性--@Input属性+“Change”
@Input() name : string; @Output() nameChange = new EventEmitter<string>();
使用V1,您现在可以使用ngModel语法绑定到子组件
[(name)]="firstname"
V2。只需使用您喜欢的名称创建一个@Input和@Output属性
@Input() age : string; @Output() ageChanged = new EventEmitter<string>();
使用V2,您必须创建两个属性才能获得两种方式的绑定
[age]="alter" (ageChanged)="alter = $event"
父组件
import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: `<p>V1 Parentvalue Name: "{{firstname}}"<br/><input [(ngModel)]="firstname" > <br/><br/> V2 Parentvalue Age: "{{alter}}" <br/><input [(ngModel)]="alter"> <br/><br/> <my-child [(name)]="firstname" [age]="alter" (ageChanged)="alter = $event"></my-child></p>` }) export class AppComponent { firstname = 'Angular'; alter = "18"; }
子组件
import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'my-child', template: `<p>V1 Childvalue Name: "{{name}}"<br/><input [(ngModel)]="name" (keyup)="onNameChanged()"> <br/><br/> <p>V2 Childvalue Age: "{{age}}"<br/><input [(ngModel)]="age" (keyup)="onAgeChanged()"> <br/></p>` }) export class ChildComponent { @Input() name : string; @Output() nameChange = new EventEmitter<string>(); @Input() age : string; @Output() ageChanged = new EventEmitter<string>(); public onNameChanged() { this.nameChange.emit(this.name); } public onAgeChanged() { this.ageChanged.emit(this.age); } }