首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Angular2 -组件变量/组件类属性上的双向数据绑定?

Angular2 -组件变量/组件类属性上的双向数据绑定?
EN

Stack Overflow用户
提问于 2016-02-26 06:26:00
回答 2查看 24.1K关注 0票数 23

在Angular2 (Beta6)中,我有一个主菜单组件。

代码语言:javascript
复制
<mainmenu></mainmenu>

我想为宽或窄绑定一个布尔值。所以我把它写成了:

代码语言:javascript
复制
<mainmenu [(menuvisible)]="true"></mainmenu>

但是我想要的(我认为)是绑定到一个javascript类属性(因为我可能有其他东西要绑定,但是我想通过在组件中使用一个类来保持整洁)。

我得到一个错误

异常:模板分析错误:属性名称'menumodel.visible‘无效(“

](menumodel.visible)="menumodel.visible">

如果我用一个变量而不是一个类来尝试同样的方法,我会得到:

模板解析错误:解析器错误:意外的标记'=‘

然而,这(单向绑定?)看起来确实有效(但我可能想触发菜单从另一个组件变宽/变窄,所以我觉得这应该是一个双向数据绑定属性):

代码语言:javascript
复制
<menu [vis]="true"></menu>

这是我的菜单组件的一小部分:

代码语言:javascript
复制
@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视图模型类

代码语言:javascript
复制
export class MainMenuVM {
    public visible: boolean;
    constructor(
    ) { this.visible = true; }
}

我正在尝试创建一个菜单,它有图标和文本,但可以缩小到只显示图标。我将向上向父组件发出此事件,以改变菜单旁边容器的位置。触发内容容器最大化将触发菜单变窄-我不是说这是最好的方法,但我想在深入之前解决这个特定的问题。

请注意:我在这里并不是将数据绑定到输入控件--只是将数据绑定到组件,这样我就可以修改UI了。

这是来自Angular的小抄

代码语言:javascript
复制
<my-cmp [(title)]="name">   
Sets up two-way data binding. Equivalent to: <my-cmp [title]="name" (titleChange)="name=$event">

提前感谢!

更新

集成来自接受答案的代码,并根据我的特定用例进行调整,这里是最终的工作代码:

app.html

代码语言:javascript
复制
...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 (根)

代码语言:javascript
复制
export class AppComponent implements OnInit{
   menuvisible: Boolean;
}

menu.component.ts (根的子级)

代码语言:javascript
复制
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

代码语言:javascript
复制
<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>

记住导入你需要的东西。

从‘angular2/

’导入{Component,EventEmitter,OnInit,Input,Output};

在You Tube上强烈推荐这个视频:Angular 2 Tutorial (2016) - Inputs and Outputs

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-26 06:29:12

对于双向绑定,您需要类似以下内容:

代码语言:javascript
复制
@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);
    // }
}

并像这样使用它

代码语言:javascript
复制
@Component({
  selector: 'some-component',
  template: `
<menu [(menuvisible)]="menuVisibleInParent"></menu>
<div>visible: {{menuVisibleInParent}}</div>
`
  directives: [MenuComponent]
})
class SomeComponent {
  menuVisibleInParent: boolean;
}
票数 33
EN

Stack Overflow用户

发布于 2017-05-16 03:17:39

我创建了一个短的plunkr。

ngModel Like Two-Way-Databinding for components

至少有两种方法可以为组件创建双向数据绑定

V1:使用类似语法的ngModel,您必须在@Output属性名称末尾的@Input属性+ "Change“行中创建一个同名的@Output属性

代码语言:javascript
复制
@Input() name : string;
@Output() nameChange = new EventEmitter<string>(); 

使用V1,您现在可以使用ngModel语法绑定到子组件

代码语言:javascript
复制
[(name)]="firstname"

V2。只需创建一个@Input和@Output属性,并使用您喜欢的名称

代码语言:javascript
复制
@Input() age : string;
@Output() ageChanged = new EventEmitter<string>();

使用V2时,您必须创建两个属性来实现双向数据绑定

代码语言:javascript
复制
[age]="alter" (ageChanged)="alter = $event"

父组件

代码语言:javascript
复制
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"; 
}

子组件

代码语言:javascript
复制
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);
     }
 }
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35639650

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档