/ / Dlaczego warunkowy element div nie działa w kanciastym - kątowym, maszynopisowym, firebase

Dlaczego warunkowy div nie działa w kanciastym - kątowym, maszynopisowym, firebase

Mam trzy warunkowe div na stronie i próby pokazania każdego div na określonej warunku.

<div *ngIf="isAvailable=="true"">
<form>
<div class="form-group">
<label for="Admin">Deployment Admin</label>
<input type="text" class="form-control" id="name" name="name" aria-describedby="name" [(ngModel)]="NewDeployAdmin.name">
</div>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="email" name="email" aria-describedby="email" placeholder="Enter email" [(ngModel)]="NewDeployAdmin.email">

</div>
<div class="form-group">
<label for="exampleInputPassword">Password</label>
<input type="password" class="form-control" id="paswsword" name="password" placeholder="Password" placeholder="Enter al least 6 character" [(ngModel)]="NewDeployAdmin.password">
</div>
<button type="submit" class="btn btn-primary" (click)="fnCreateDeployAdmin()">Submit</button>
</form>
</div>

<div *ngIf="isAvailable=="false"">
<button  type="submit" class="btn btn-warning" (click)="fnDisableAccount()">Disable Account</button> | <button  type="submit" class="btn btn-primary" (click)="fnUpdateDeployAdmin()">Reset Credential</button>
</div>

W .ts stronę, ustawiam jest dostępny w innym stanie i chcesz wyświetlić odpowiednie div. Ale to nie działa.

Chcę renderować odpowiadający div. Oto kod, w którym ustawiam jest dostępny

isDeploymentAdminAvailable(deployment){
let customQuery = {
equalTo: this.selectedDeploy.key
}

this.authService.fnGetDataUsingCustomQuery(FirebaseDb.firebasedeploymentAdminTable, customQuery).subscribe(
(rec: any) => {
rec.forEach((reccord: any) => {
reccord.key = reccord.$key;
});
this.deployAdminData = JSON.parse(JSON.stringify(rec));

});

if(this.deployAdminData!=null && Object.keys(this.deployAdminData).length>0){
return "true";

}

return "false";

}

I funkcja, z której to nazywam isDeploymentAdminAvailable metoda jest

deploymentOnClick($event, deployment){

this.isAvailable = "None";

this.selectedDeploy = deployment;

this.isAvailable = this.isDeploymentAdminAvailable(deployment);
}

Odpowiedzi:

1 dla odpowiedzi № 1

Wracasz "true" i "false" są to łańcuchy, które obaj oceniają jako prawdziwe. Usuń cytaty, aby tak było true i false i ustaw typ isAvailable do boolean. i niech porównanie * ngIf isAvailable lub !isAvailble

Szczerze mówiąc, jest bardzo źle z twoim kodem. JavaScript ma jeden wątek, powinieneś mieć swoje oświadczenia dotyczące zwrotu. tj if powinien nastąpić else. Widzę tylko dwa warunkowe divy ... Korzystanie true false lub None nie jest dobrym pomysłem. Imiona true i false sugerować związek binarny, jeśli chcesz więcej niż dwie opcje, powinieneś użyć innych terminów.

Również to jest maszynopis. Musisz wpisać swoje parametry. Wszystkie są typu any.

Również przekazujesz wdrożenie do isDeploymentAdminAvailable i nie używaj go w dowolnym miejscu ...

Również w javascript musisz użyć === i !== operatorzy, gdzie tylko jest to możliwe.

Opisz występujące zachowanie. Czy nie renderujesz ani div? Proszę zmień isAvailable do boolowskiej i powiedz mi, co się dzieje. Posługiwać się console.log w if oświadczenie i na zewnątrz i sprawdź konsolę, aby zobaczyć, który warunek jest spełniony i czy tego się spodziewasz, kiedy dokonasz tych zmian, a ja ci pomogę.

Jak @yurzui stwierdził problem z twoim kodemprawie na pewno nie używasz asynchronicznego kodu. Czekamy, aż baza ogniowa zwróci wartość, a następnie od razu sprawdza tę wartość, zanim ona powróci. Wyobrażam sobie, że kod teraz wraca "false" od this.deployAdminData zawsze będzie null ponieważ nie czekasz na odpowiedź z firebase i właśnie przez nią przechodzisz.

Aby to naprawić, jednym podejściem byłoby oddzielenie if warunek do oddzielnej funkcji i wywołaj tę funkcję na końcu subscribe.

this.authService.fnGetDataUsingCustomQuery(FirebaseDb.firebasedeploymentAdminTable, customQuery).subscribe(
(rec: any) => {
rec.forEach((reccord: any) => {
reccord.key = reccord.$key;
});
this.deployAdminData = JSON.parse(JSON.stringify(rec));
this.isAvailable = this.yourFunctionName(deployAdminData);
});
}

yourFunctionName(deployAdminData: any) {
if(deployAdminData !== null &&
Object.keys(deployAdminData).length > 0) {
return true;
} else { return false; }
}

edytuj także:

deploymentOnClick($event, deployment){
//this.isAvailable = "None";
this.selectedDeploy = deployment;
this.isDeploymentAdminAvailable(deployment);
}

Następnie możesz użyć *ngIf="isAvailable". Uwaga Ustawiłem deployAdminData pisać any w parametrze. To nie jest najlepsza praktyka i musisz ją wymienić any z typem danych.


0 dla odpowiedzi nr 2

Podstawowy powód isAvailable nie jest już kontrolowana widoczność div została już podana - wartość powinna być ustawiona w subskrypcji.

Jest jednak jasne, że aplikacja to robi nie działa, gdy typ flagi zostanie zmieniony na Boolean.

Wydaje mi się, że logika aplikacji polega na tym, że przed pobraniem danych ty pokaż ani z div (isAvailable === "None"), a następnie po pobraniu pokaż jeden lub inny div na podstawie zwróconej wartości.


Refaktoryzacja zgodnie z najlepszą praktyką kątową

Możesz wcisnąć kod isDeploymentAdminAvailable do authService usługa.

W ten sposób

  • cała logika związana z pobieraniem jest w jednym miejscu
  • twoje testy pójdą gładko
  • możesz usunąć zależność Firebase od komponentu
  • ujawnić dane i isAvailable własność jako Observables.

Obserwowalne konwencje

Powszechną praktyką jest dołączanie $ do końca zmiennych, które są obserwowalne, aby było oczywiste, że potrzebują async rura w szablonie, lub subscribe w kodzie ts.


Dlaczego obserwowalne zmienne?

Aplikacja wyrenderuje tę stronę na długo przed pobieraniem przez bazę danych Firebase wartości, dzięki zastosowaniu zmiennych obserwowalnych i zmiennej async w szablonie, widok zostanie automatycznie zaktualizowany po zakończeniu pobierania.

Ponadto, gdy baza danych ulegnie zmianie, Firebase może przekazywać nowe wartości, więc w przypadku obserwowalnych właściwości widok reaguje na te zmiany bez potrzeby wyraźnego odświeżania.

Jedyne, co nie jest dla mnie jasne, to związek pomiędzy NewDeployAdmin i this.deployAdminData.
Może być konieczne dodanie subscribe() lub async rury w zależności od tego, jak te dwa elementy są powiązane.


authService.ts

@Injectable()
export class AuthService {

public deployAdminData$ = new BehaviorSubject({});
public isAvailable$ = new BehaviorSubject("None");  // initial value set to "None"

private fnGetDataUsingCustomQuery(...) {
...
}

public isDeploymentAdminAvailable(key) {
let customQuery = {
equalTo: key
}
this.fnGetDataUsingCustomQuery(FirebaseDb.firebasedeploymentAdminTable, customQuery)
.subscribe(rec => {
rec.forEach(reccord => reccord.key = reccord.$key );
const data = JSON.parse(JSON.stringify(rec));  // this may not be needed
this.deployAdminData$.next(data);
this.isAvailable$.next(
data && Object.keys(data).length ? "true" : "false";
)
});
}

myComponent.html

<div *ngIf="(isAvailable$ | async)=="true"">
<form>
<div class="form-group">
<label for="Admin">Deployment Admin</label>
<input type="text" class="form-control" id="name" name="name"
aria-describedby="name" [(ngModel)]="NewDeployAdmin.name">
</div>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="email" name="email"
aria-describedby="email" placeholder="Enter email"
[(ngModel)]="NewDeployAdmin.email">
</div>
<div class="form-group">
<label for="exampleInputPassword">Password</label>
<input type="password" class="form-control" id="paswsword" name="password"
placeholder="Password" placeholder="Enter at least 6 characters"
[(ngModel)]="NewDeployAdmin.password">
</div>
<button type="submit" class="btn btn-primary
(click)="fnCreateDeployAdmin()">Submit</button>
</form>
</div>

<div *ngIf="(isAvailable$ | async)=="false"">
<button  type="submit" class="btn btn-warning"
(click)="fnDisableAccount()">Disable Account</button>
<button  type="submit" class="btn btn-primary"
(click)="fnUpdateDeployAdmin()">Reset Credential</button>
</div>

myComponent.ts

// Set up observable pipeline that responds to changes in the database.
private isAvailable$ = this.authService.isAvailable$;
private this.deployAdminData$ = this.authService.this.deployAdminData$;

isDeploymentAdminAvailable(deployment) {
this.authService.isDeploymentAdminAvailable(this.selectedDeploy.key)
}

-1 dla odpowiedzi nr 3

Zamiast porównywać i używać wyrażenia w szablonie, należy bezpośrednio przekazać wartość jest dostępny do szablonu.

<div *ngIf="isAvailable">
...
</div>
<div *ngIf="!isAvailable">
...
</div>

Mam nadzieję, że to może pomóc.