Angular *ngIf with async pipe inner condtion based on the resulting model - javascript

I'd be a happy man if someone could explain why the following is not working as expected please?
The hasCreative is a boolean but regardless of its true/false value, the <li> is always displayed. Any suggestions would be great. Thank you.
<ng-container *ngIf="uiModel$ | async as model">
<ul class="nav" style="padding-bottom: 30px;">
<li *ngIf="model.hasCreative" class="nav-item">
<a class="nav-link active" routerLinkActive="active" [routerLink]="['']">Home</a>
</li>
</ul>
</ng-container>
export class UserInterfaceModel {
hasCreative: boolean;
}
#Injectable({
providedIn: 'root'
})
export class UserInterfaceService {
user: CognitoUser;
userLoggedIn = false;
private userInterfaceModelSubject$: Subject<UserInterfaceModel> = new Subject();
userInterfaceModel$ = this.userInterfaceModelSubject$.asObservable();
constructor(private authService: AuthService) {
combineLatest([this.authService.onUserLoaded$]).subscribe(([currentUser]) => {
this.user = currentUser;
this.userLoggedIn = true;
this.buildUserInterfaceModel();
});
}
buildUserInterfaceModel(){
const model = new UserInterfaceModel();
if (this.userLoggedIn && this.user !== null){
model.hasCreative = this.user.getSignInUserSession().getIdToken().payload.creative;
}
this.userInterfaceModelSubject$.next(model);
}
}

Try using this:
<ng-container *ngIf="uiModel$ | async as model; else loading">
<ul class="nav" style="padding-bottom: 30px;">
<li *ngIf="model.hasCreative === true " class="nav-item">
<a class="nav-link active" routerLinkActive="active" [routerLink]="['']">Home</a>
</li>
</ul>
</ng-container>
<ng-template #loading>
Loading stuff...
</ng-template>
If loading template will render it means your Observable has no value. If it dosnt work too, try render the value of model.hasCreative by adding somethin like this:
<span>{{model.hasCreative}}<span>
out of <ul> tag to see if model.hasCreative has true/false value or not.

Related

document.querySelector in Angular

I have a list where each li has unique data-id.
<ul class="list">
<li class="list__el"
*ngFor="let item of cars"
data-id="{{ item.id }}">
</li>
</ul>
In JS I would wrote
let myLi = document.querySelector(`.list__el[data-id="${item.id}"]`)
How to correctly rewrite it for Angular?
Use #ViewChildren and a template reference such as #listItem.
#Component({
template: `<ul class="list">
<li #listItem class="list__el"
*ngFor="let item of cars"
data-id="{{ item.id }}">
</li>
</ul>`
})
export component MyComponent implements AfterViewInit {
// Note that the parameter here relates to the #listItem in the template.
#ViewChildren('listItem')
public listItems!: QueryList<ElementRef<HTMLLIElement>>
public ngAfterViewInit() {
console.log(
this.listItems.find(itm =>
itm.nativeElement.getAttribute('data-id') === 'my-element-id'
)
)
}
}

vuejs2 child component data not updating in laravel5.4

Here is my replies.vue file. Here what i am doing is when this replies component is created, i call a fetch() method that loads some data from the server:
//Replies.vue
<template>
<div>
<div v-for="(reply, index) in replies_with_pagination.data">
<reply :attributes="reply" :key="reply.id" :current_user_id="auth_user_id" #iamdeleted="updateCollection(index)"></reply>
</div>
<pagination :current_paginated_dataSet="replies_with_pagination"></pagination>
</div>
</template>
<script>
import Reply from './Reply.vue';
export default{
components: { Reply },
props: ['all_replies','auth_user_id','thread_id'],
data() {
return {
all_reply_items: this.all_replies,
replies_with_pagination: '',
}
},
methods: {
fetch: function(){
let vm = this;
axios.get(route('replies.paginated',{ 'thread' : this.thread_id
}))
.then(function(serverResponse){
vm.replies_with_pagination = serverResponse.data;
});
},
},
created() {
this.fetch();
}
And then i am passing that to the pagination component via the current_paginated_dataSet props. Here is the code for pagination.vue
//Pagination.vue
<template>
<div>
<nav aria-label="...">
<ul class="pagination">
<li class="page-item disabled" v-show="current.prev_page_url">
<a class="page-link" href="#" tabindex="-1">Previous</a>
</li>
<li class="page-item"><a class="page-link" href="#">1</a></li>
<li class="page-item active">
<a class="page-link" href="#">2 <span class="sr-only">(current)</span></a>
</li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item" v-show="current.next_page_url">
<a class="page-link" href="#">Next</a>
</li>
</ul>
</nav>
</div>
</template>
<script>
export default{
props: ['current_paginated_dataSet'],
data() {
return {
current: this.current_paginated_dataSet,
}
},
}
</script>
As you can see i am using this property to initialize a data called current in the pagination component. This current_paginated_dataSet property was initialized at the replies component to the value of FALSE, which, upon fetching the data from server was then reset to some object returned by the server.
My problem is the previous and next buttons on the pagination component are not visible. It seems the current data property on the pagination component is not getting the updated value from the replies component which updates after loading data from server. It is always set to the intial value of FALSE that it received from parent root component.
What am i doing wrong here?
EDIT
it works if instead of referring to the current data property i directly refer to the current_paginated_dataSet props in the previous and next buttons, like so:
// this works:
<li class="page-item disabled" v-show="current_paginated_dataSet.prev_page_url">
<a class="page-link" href="#" tabindex="-1">Previous</a>
</li>
But i want to achieve this by referring to the data property current. How can i do that?

Angular2 - Get a specific element in the DOM and change it's class

Let's say I have an unordered list like so
<div>
<ul class="data-container">
<li #H1>00</li>
<li #H2>01</li>
<li #H3>02</li>
<li #H4>03</li>
<li #H5>04</li>
...
</ul>
</div>
What's the best way to get a element based on it's local variable using ViewChild then retrieving it's value and give it a special class (say class="active")
Is there a filter or find function I can use here?
Also, let's say I want to select one of the items, is there a better way than using (click)="SelectElement()" on all of them?
You can create a LiDirective to mark all LI. After that you can use all API provided my QueryList like find,filter, reduce, toArray ...
#Directive({
selector:'li'
})
export class LiDirective{}
#Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<div>
<ul class="data-container">
<li>00</li>
<li #H2>01</li>
<li #H3>02</li>
<li #H4>03</li>
<li #H5>04</li>
</ul>
</div>
</div>
`,
})
export class App {
#ViewChildren(LiDirective, {read:ElementRef}) lis: QueryList<any>;
name:string;
constructor(private renderer: Renderer2) {
this.name = `Angular! v${VERSION.full}`
}
ngAfterViewInit() {
let second = this.lis.toArray()[2];
this.renderer.setStyle(second.nativeElement, 'color', 'blue');
}
}

How to show and hide side menu in angular2

In my application i have to implement hide and show side menu. By default the page menu is open while clicking the toggle menu i have to hide the side menu. How can i implement this.
what i have is:
app.component.html, nav.component.html
<div class="menu-toggler sidebar-toggler">
<span></span>
</div>
<ul>
<li class="nav-item ">
<a class="nav-link nav-toggle">
<i class="icon-diamond"></i>
<span class="title">Name</span>
<span class="arrow"></span>
</a>
</li>
</ul>
Myservice.ts
export class GlobalService {
public collapse;
constructor() { }
setValue(val: boolean) {
this.collapse = val;
}
getValue() {
return this.collapse;
}
EDIT
app.component.html
<div *ngIf="!toggle()"class="menu-toggler sidebar-toggler">
<span></span>
</div>
app.component.ts
import { GlobalService } from "path";
export class AppComponent {
toggle() {
this.globalService.setValue(false);
}
}
how can i hide this list(in nav.html) while clicking menu toggle (app.compnent.html)? Any help will really appreciable. i am new to angular.
If use of service is not the priority then you can simply maintain simple variable to do this task.
Your app.component.ts
export class AppComponent {
showMenu : boolean = true;
}
Your app.component.html
<div (click)="showMenu = !showMenu" class="menu-toggler sidebar-toggler"><span></span>
</div>
<ul *ngIf="showMenu">
<!-- used showMenu to hide/show -->
<li class="nav-item ">
<a class="nav-link nav-toggle">
<i class="icon-diamond"></i>
<span class="title">Name</span>
<span class="arrow"></span>
</a>
</li>
</ul>
hope this helps ...
For this ,
You can make a CommonService to store the state of menu or and use that Service to make toggle you menu.
You can also use #Input #Output , in case you are having parent child relation between components.
Method will depend on how is your project/file structure.
You can create a service and preferably make a static variable inside to get and set the visibility state of the menu. By this you could directly set and get the variable by using ComponentName.variableName.
to play with the visibility you could use(Sorry if there is any syntax errors)
1> Set the document.getelementbyid("idofelement").display= none or block
2>use *ngIf="someboolean" where you should set the boolean in your ts file

How to hide elements based on user in FireBase and Angular

I'm starting to use Firebase with AngularJS.
Coming from a php/serverside rendered pages.
I dont't get how we're supposed to hide parts of an app to some users.
I have basically 3 levels of users (guests / members / admins)
I could hide with a ng-show based on user, but this only hides client-side.
Data is still sent to the user
Real life example:
The menu items are different based on user level.
I was thinking about using ngshow and check for the uuid , but then again, is exposing the admins uuid a good idea? sounds terrible to me.
Then I thought about putting the menu inside a database and requesting the elements.
Not all users would access all items, but this means a lot of 'unauthorised access attempts on purpose'
What is the correct way of handling this? I feel like I've missed something important about client-only apps relying on Firebase services.
Look at userStatus method in service layer and it usage in other layers.
Service layer :
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { AngularFireAuthModule, AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
#Injectable()
export class AuthService {
user: Observable<firebase.User>;
constructor(private fireAuth: AngularFireAuth) {
}
loginGoogle() {
this.fireAuth.auth.signInWithPopup(new firebase.auth.EmailAuthProvider())
.catch(function (error) {
alert('Please try again');
});
}
logout() {
this.fireAuth.auth.signOut();
}
userStatus() {
return this.fireAuth.authState;
}
}
Navbar Component :
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../../services/auth.service';
import { Observable } from 'rxjs/Observable';
import * as firebase from 'firebase/app';
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
user: Observable<firebase.User>;
constructor(private authservice: AuthService) {
this.user = this.authservice.userStatus();
}
ngOnInit() {
}
login() {
this.authservice.loginGoogle();
}
logout() {
this.authservice.logout();
}
}
And here is Navbar view, where you want to hide or show the elements based on if user is authenticated :
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand" routerLink="/">Firebase</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item ">
<a class="nav-link" routerLink="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" *ngIf="(user | async)?.uid" routerLink="/listings">Listings</a>
</li>
<li class="nav-item">
<a class="nav-link" *ngIf="(user | async)?.uid" routerLink="/add-listing">Add Listing</a>
</li>
</ul>
<ul class="navbar-nav navbar-right">
<li class="nav-item">
<a class="nav-link" *ngIf="!(user | async)?.uid" (click)="login()">Login</a>
<a class="nav-link" *ngIf="(user | async)?.uid" (click)="logout()">Logout</a>
</li>
</ul>
<div *ngIf="(user | async)?.uid">
<img src="{{(user | async)?.photoURL}}" style="width:30px;height:30px;">
<br> Email: {{(user | async)?.email}}
<br> Name: {{(user | async)?.displayName}}
</div>
</div>
</nav>

Categories