* ngIf对布尔变化没有反应

时间:2017-09-24 10:00:30

标签: angular angular2-directives angular-directive

以下是一些代码。同样的模式(afaik)适用于英雄教程。

login.component.html:

wrongCredentialsInserted: boolean = false;

//...      

onSubmit(login: LoginDto): void {
        console.log(`User '${login.username}' attempts to login...`);
        if (this.authService.login(login.username, login.password)) {
          this.location.back();
        } else {
          this.wrongCredentialsInserted = true; //This line gets executed!
        }
      }

login.component.ts:

wrongCredentialsInserted

即使我将*ngIf="wrongCredentialsInserted === true"设置为true,也不会显示该消息。它设置为true,我已经验证了。我也试过像import {AbstractControl, FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms'; import {routerTransition} from '../../router.transition'; import {Component} from '@angular/core'; import {AuthService} from '../auth.service'; import {LoginDto} from './login-dto'; import {Location} from '@angular/common'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'], animations: [routerTransition()] }) export class LoginComponent { private readonly USERNAME: string = 'username'; private readonly PASSWORD: string = 'password'; myForm: FormGroup; username: AbstractControl; password: AbstractControl; message: string; wrongCredentialsInserted = false; constructor(public fb: FormBuilder, public authService: AuthService, public location: Location) { this.message = ''; this.myForm = fb.group({ username: ['', Validators.required], password: ['', Validators.required] }); this.username = this.myForm.controls[this.USERNAME]; this.password = this.myForm.controls[this.PASSWORD]; } onSubmit(login: LoginDto): void { console.log(`User '${login.username}' attempts to login...`); if (this.authService.login(login.username, login.password)) { this.location.back(); } else { this.wrongCredentialsInserted = true; } } login(username: string, password: string): boolean { this.message = ''; if (!this.authService.login(username, password)) { this.message = 'Incorrect credentials.'; setTimeout( function () { this.message = ''; }.bind(this), 2500); } return false; } logout(): boolean { this.authService.logout(); return false; } } 这样的东西,因为我在其他地方看过,但它没有用。 我读到这可能与#34;单向数据流有关,从Angular 2"开始,但我知道我们能够在公司的A2 +项目中做这些事情。 AFAIK单向数据绑定仅指组件 - 组件通信。

非常感谢任何形式的帮助。

编辑:由于我所做的事情似乎有些混乱,我在这里发布了整个文件。

login.component.ts

<div class="ui raised segment">
  <form [formGroup]="myForm"
        (ngSubmit)="onSubmit(myForm.value)"
        class="ui form"
        [class.error]="!myForm.valid">

    <div class="field"
         [class.error]="!username.valid && username.touched">
      <label for="username">Username:</label>
      <input type="text"
             id="username"
             placeholder="Username"
             [formControl]="username">
      <div *ngIf="username.hasError('required') && username.touched"
           class="ui error message">
        Username is required
      </div>
    </div>

    <div class="field"
         [class.error]="!password.valid && username.touched">
      <label for="password">Password:</label>
      <input type="text"
             id="password"
             placeholder="Password"
             [formControl]="password">
      <div *ngIf="password.hasError('required') && password.touched"
           class="ui error message">Password is required
      </div>
    </div>

    <div class="ui grid">

      <div class="two wide column middle aligned">
        <button type="submit"
        class="ui button"
        [class.disabled]="!myForm.valid">Submit
        </button>
      </div>

      <div class="fourteen wide column middle aligned" *ngIf="wrongCredentialsInserted">
        <div
          class="ui error message">Invalid credentials
          </div>
        </div>

      </div>

    </form>
  </div>

login.component.html

@Injectable()
export class AuthService {

  constructor(private http: Http) {
  }

  login(user: string, password: string): boolean {
    if (user === 'user' && password === 'password') {
      localStorage.setItem('username', user);
      return true;
    }

    return false;
  }

  logout(): any {
    localStorage.removeItem('username');
  }

  getUser(): any {
    return localStorage.getItem('username');
  }

  isLoggedIn(): boolean {
    console.log(`Is user logged in? ' + ${this.getUser() !== null}`);
    return this.getUser() !== null;
  }
}

login.component.css:空

auth.service.ts:

- (id)initWithNibName:(NSString *)nibName withSaveSelector:(SEL)saveSelector forTarget:(id)target

5 个答案:

答案 0 :(得分:2)

我之前也有类似的问题, * ngIf 不打算更改值,但这是因为我的布尔值是作为字符串从后端发送的,例如:"true"或{{1} },而我发现值得的解决方案是

"false"

希望这会有所帮助。

答案 1 :(得分:1)

*ngIf没有对模型中的变化做出反应有几个可能的原因。

更改检测未运行

您在组件上使用OnPush策略并更改组件状态,而无需手动触发CD循环。通过注入ChangeDetectorRef并使用适合您需要的方法,可以重新打开自动CD或手动触发CD。

样式会误导你

ngIf绑定可能正常工作,并且模板已正确创建和销毁,但有些样式会在视觉上模糊这一点,例如display: nonevisibility: hidden等。确保通过打开浏览器的开发工具来检查页面。

发生了未被捕获的错误

如果在开发过程中没有打开控制台,很容易错过。可能有一个错误导致代码破坏,Angular无法从中恢复;从而防止任何进一步的CD周期运行并更新DOM。一定要有一个打开的控制台来检查错误。

您甚至没有更改模型

Angular是一个框架,您可以声明性地指定基于模型创建DOM的方式。你可以通过编写模板来完成。如果您的模型没有改变,DOM也不会改变。确保正在运行正确的代码段。快速执行此操作的方法是在更改变量的代码附近放置console.log。您还可以在浏览器的开发工具中放置断点,或者使用Chrome的实用程序扩展(例如Augury)独立于基于模板呈现的模式检查模型。

答案 2 :(得分:1)

在我的情况下,发生此问题是因为更改发生在Angular区域之外。在变更检测周期内运行代码可解决此问题。在这种情况下,您几乎没有选择

  • 将第三方函数包装在zone.run中(将NgZone注入控制器)

    myFunctionRunByAThirdPartyCode(){
      this.ngZone.run(this.myFunction);
    }
    
  • 将函数包装在setTimeout中

    myFunctionRunByAThirdPartyCode(){
      setTimeout(this.myFunction,0);
    }
    
  • 手动调用detectChanges()(将ChangeDetectorRef注入控制器)

    myFunctionRunByAThirdPartyCode(){
     this.changeDetectorRef.detectChanges();
    }
    

答案 3 :(得分:0)

我的问题是,*ngIf出现在<form></form>标记内。如果我把它放在外面,一切都有效。我知道angular使用form标签来注入它们的表单模块,但我没想到会出现这样的行为。因此,当表单本身有其他验证错误时,我的验证错误才会弹出。

答案 4 :(得分:0)

某处验证将bool变量触发到该状态。 (类似于“角反应形式”的“ get”函数),请使用console.log()评估变量状态