Angular 2 material : sidenav toggle from component - javascript

I'm using Angular 2 Material sidenav in my project this way:
<md-sidenav-layout>
<md-sidenav #start mode="side" [opened]="true">
<md-nav-list>
</md-nav-list>
</md-sidenav>
<button md-button (click)="start.toggle()">Close</button>
<router-outlet></router-outlet>
</md-sidenav-layout>
How to call start.toggle() from my component instead of element with click event?
Thank you for reading

You want to declare a ViewChild in your controller that references the MdSidenav inside your component, like this:
// Sidemenu
#ViewChild('start') sidenav: MdSidenav;
where start is the name of the component you want to reference, in this case the sidenav.
Next you can call methods on that sidenav, like this.sidenav.toggle() inside your controller's functions.
https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-view-child

Pass the object to your function.
<md-sidenav-layout>
<md-sidenav #start mode="side" [opened]="true">
<md-nav-list>
</md-nav-list>
</md-sidenav>
<button md-button (click)="randomName(start)">Close</button>
<router-outlet></router-outlet>
</md-sidenav-layout>
import {Component} from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html'
})
export class AppComponent {
constructor() {
}
randomName(start: any) {
start.toggle();
}
}

The simplest way for was to pass the drawer to the component that triggers the toggle.
Html:
<mat-drawer #drawer mode="side">
....
</mat-drawer>
<another-component [drawerRef]="drawer"><another-component/>
another-component TS:
export class AnotherComponent implements OnInit {
#Input() drawerRef: MatDrawer;
...
}
another-component HTML:
<button (click)="this.drawerRef.toggle()">
Where another-component is the component that controls the toggle action.

<md-sidenav #sidenav class="example-sidenav" opened="false">
<div class="example-sidenav-content">
<button type="button" md-button (click)="toogleNav(sidenav)">
toogle
</button>
</div>
</md-sidenav>
And in your ts:
export class AppComponent {
toogleNav(nav: any) {
if (nav.opened) {
nav.close()
} else {
nav.open();
}
}
}

Related

Angular 6 modal opening on same page not in popup

I am have an angular 6 project that includes a toolbar on the top of the page with a "Sign In" button. When I click on this button, I want a modal dialog to appear.
However, I ran there are two issues illustrated in the screenshot below. The first is when I load the page, both modals (outlined in red) are loaded. They should only appear if the appropriate button is clicked.
Stackblitz project is at below link:
https://stackblitz.com/github/eugene01a/online-exam/tree/master/frontend
The second issue is why are they not appearing in their own dialog popup?
import {
Component,
OnInit
} from '#angular/core';
import {
ModalService
} from "./_services";
import './_content/app.less';
import './_content/modal.less';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent implements OnInit {
authenticated = false;
constructor(private modalService: ModalService) {}
ngOnInit() {}
openModal(id: string) {
this.modalService.open(id);
}
closeModal(id: string) {
this.modalService.close(id);
}
}
<!-- main app container -->
<mat-toolbar color="primary" class="mat-elevation-z10">
<button mat-button>Online Exams</button>
<button mat-button>About</button>
<!-- This fills the remaining space of the current row -->
<span class="fill-remaining-space"></span>
<button mat-button (click)="openModal('signin-modal')" *ngIf="!authenticated">Sign In</button>
<button mat-button (click)="openModal('signout-modal')" *ngIf="authenticated">Sign Out</button>
</mat-toolbar>
<div class="view-container">
<router-outlet></router-outlet>
</div>
<jw-modal id="signin-modal">
<h1>Sign in button clicked</h1>
<button (click)="closeModal('signin-modal');">Close</button>
</jw-modal>
<jw-modal id="signout-modal">
<h1>Sign Out button clicked</h1>
<button (click)="closeModal('signout-modal');">Close</button>
</jw-modal>

Swimlane/ngx-ui change buttons' labels from Alert/Prompt

I´m using ngx-ui from Swimlane: https://swimlane.github.io/ngx-ui/
There is an alert/promp/confirm component that behaves as the browser's native.
The problem is that there is nothing in the docs that says if it is possible to change the label from the buttons.
There is only one example:
alertService.confirm({ title: 'Alert SOC', content: 'Intrusion Happened!!!' })
Does anyone know if it´s possible?
I don't know if it's possible with the alert service, but it looks easy to customize if you use a dialog.
<ng-template #dialogTmpl let-context="context">
<p>Custom dialog</i></p>
<button
type="button"
class="btn">
Custom button text
</button>
</ng-template>
<button
type="button"
class="btn"
(click)="openDialog({ title: 'Alert!', template: dialogTmpl })">
Open Dialog
</button>
And in the .ts:
import { DialogService } from '#swimlane/ngx-ui';
#Component({
selector: 'app',
templateUrl: './app.template.html'
})
export class AppComponent {
#ViewChild('dialogTmpl') dialogTpl: TemplateRef<any>;
constructor(public dialogMngr: DialogService) { }
openDialog(options): void {
this.dialogMngr.create(options);
}
}

JQuery search limited to Angular component's DOM

I would like to use JQuery inside my Angular components for DOM manipulation, but I would like to limit JQuery searches to the component's markup it's used in.
I'm trying using Shadow DOM, so I have this component:
import { Component, OnInit, ViewEncapsulation } from '#angular/core';
import * as $ from 'jquery';
#Component({
selector: 'app-layout',
templateUrl: './layout.component.html',
styleUrls: ['./layout.component.less'],
encapsulation: ViewEncapsulation.Native
})
export class LayoutComponent implements OnInit {
constructor() { }
ngOnInit() {
}
toggleSidebar(): void {
$('.main-sidebar').toggleClass('active');
$('.content-wrapper').toggleClass('expanded');
}
}
Here's the HTML:
<div class="wrapper">
<header class="main-header">
Logo
<nav class="navbar">
<button type="button" id="sidebar-collapse" class="btn btn-info navbar-btn" (click)='toggleSidebar()'>
<i class="fa fa-align-left"></i>
</button>
</nav>
</header>
<aside class="main-sidebar">
<section class="sidebar">
Sidebar
</section>
</aside>
<div class="content-wrapper">
<section class="content">
Content
</section>
</div>
</div>
If I remove the encapsulation configuration, it works, but if I leave it in place, JQuery can't find the elements searched. I would like to know how can I make JQuery find those elements. Is there any other way of limiting JQuery searches apart from using Shadow DOM?
Why would you do menu toggling with jQuery?
It is not good practice to use it with Angular application. Let Angular do it.
You can do it with host binding
HTML
<nav class="navbar">
<button type="button" id="sidebar-collapse" class="btn btn-info navbar-btn"
(click)='toggleSidebar()'>
<i class="fa fa-align-left"></i>
</button>
</nav>
<aside class="main-sidebar" [ngClass]="{'menu_open': menuOpen}">
<section class="sidebar">
Sidebar
</section>
</aside>
Component
import { Component, HostBinding, OnInit } from '#angular/core';
export class LayoutComponent implements OnInit {
// set it closed by default
#HostBinding('class.menu_open') public menuOpen = false;
....
toggleSidebar() {
this.menuOpen = !this.menuOpen;
}
...
}

how bind md-input to md-slider value angular2

I'm developing an app with Angular 2.0/meteor, and I don't know how to bind an input to md-slider.
Here's the component html :
<div class="panel-body">
<form [formGroup]="filtreForm" #f="ngForm">
<span class="panel-title"> <i class="glyphicon glyphicon-retweet"> Paramétrages 0 </i></span>
<md-slide-toggle>On</md-slide-toggle>
<div *ngFor="let filtre of filtres | async">
<div *ngFor="let filtr of filtre.arguments">
<span class="panel-title" > <i class="glyphicon glyphicon-retweet"> {{filtr.name}} </i></span>
<md-input-container class="example-full-width" >
<input mdInput placeholder="{{filtr.name}}" formControlName="{{filtr.name}}" value="{{filtr.value}}">
</md-input-container>
<md-slider
thumb-label
[min]="'0'"
[max]="'200'"
[value]="filtr.value">
</md-slider>
</div>
</div>
<div class="btn-group people-pager">
<button type="button" class="btn btn-success btn-quirk" (click)="appliquerFiltre()"><i class="fa fa-tencent-weibo Try it"></i> Appliquer ce filtre</button>
</div>
</form>
</div>
Here's the component ts :
import {Component, ViewEncapsulation, OnInit, NgZone, Input} from '#angular/core';
import { Router } from '#angular/router';
import { Meteor } from 'meteor/meteor';
import { Observable } from 'rxjs';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
//Collection import
import { Filtres } from '../../../../both/collections/filtres.collection';
import {Filtre} from "../../../../both/models/filtre.model";
import template from './tpl.dashboard.component.html';
#Component({
selector: 'traitement_par_lot',
encapsulation: ViewEncapsulation.None,
template
})
export class TPLcomponent implements OnInit{
filtres: Observable<Filtre[]>;
filtreForm: FormGroup;
constructor(
private formBuilder: FormBuilder, private router: Router
) {}
ngOnInit(){
this.filtreForm = this.formBuilder.group({
spread:['',Validators.required],
density:['',Validators.required],
curviness:['',Validators.required],
reseed:['',Validators.required],
});
this.filtres = Filtres.find({}).zone();
console.log(this.filtres);
}
appliquerFiltre(){
}
}
This doesn't work. for now i can get the initial value from the slider but it's doesn't change when i slide
Thanks in advance
For update the value while slidering, you can use change or input event of md-slider, and get the current value from it's event.value.
change event will be fired only after the end of you slide.
input event will be fired immediately when the value of slider changes
you can choose the better one for your situation.
take a look at this plunker.

How to display simple modal with ng-bootstrap (Angular 2)

I'm trying to show a simple Modal with Ng2-bootstrap as per the following page: https://ng-bootstrap.github.io/#/components/modal
However I am getting errors such as:
Error in ./AppComponent class AppComponent - inline template:7:0 caused by: Missing modal container, add <template ngbModalContainer></template> to one of your application templates.
ORIGINAL EXCEPTION: Missing modal container, add <template ngbModalContainer></template> to one of your application templates.
What am I doing wrong? I've got the following code to try and make this work:
Index.html:
<body>
<app-root>Loading...</app-root>
<template ngbModalContainer></template>
</body>
app.module.ts:
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
...
#NgModule({...
imports: [
BrowserModule,
FormsModule,
HttpModule,
NgbModule.forRoot() ...
app.component.ts:
import { NgbModal, NgbActiveModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
import { SasModalComponent } from './sas-modal/sas-modal.component';
...
constructor(..., private modalService: NgbModal){
}
...
open() {
console.log("trying to open");
const modalRef = this.modalService.open(SasModalComponent);
}
app.component.html
<button class="btn btn-lg btn-outline-primary" (click)="open(content)">Launch demo modal</button>
sas-modal.component.ts
import { NgbModal, NgbActiveModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
...
#Component({
selector: 'sas-modal',
templateUrl: './sas-modal.component.html',
styleUrls: ['./sas-modal.component.css']
})
export class SasModalComponent {
closeResult: string;
constructor(private modalService: NgbModal) {}
open(content) {
this.modalService.open(content);
}
}
sas-modal.component.html:
<template #content let-c="close" let-d="dismiss">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="c('Close click')">Close</button>
</div>
</template>
sas-component.ts should be : -
import { NgbModal, NgbActiveModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
...
#Component({
selector: 'sas-modal',
templateUrl: './sas-modal.component.html',
styleUrls: ['./sas-modal.component.css']
})
export class SasModalComponent {
closeResult: string;
constructor(private activeModal: NgbActiveModal) {}
}
app.module.ts Should contain SasModuleComponent in the declaration array and a
entryComponent field that contains SasModuleComponent : -
#NgModule({
imports: [ BrowserModule,
FormsModule , HttpModule, NgbModule.forRoot()],
declarations: [ AppComponent, SasModalComponent],
bootstrap: [ AppComponent ],
entryComponents: [SasModalComponent]
})
You need a entryComponent field in #NgModule()in your module file because you are loading the SasModuleComponent dynamically here this.modalService.open(SasModalComponent).
Try adding <template ngbModalContainer></template> in app-root template
Example:
#Component({
selector: 'app-root',
template: '<template ngbModalContainer></template>'
})
saurav1405's answer provided me with enough useful information to figure this out, however his solution didn't 100% work for me.
For this reason I've upvoted saurav1405's response, but couldn't claim is as the answer as I've had to do a bit more to get it to work for me.
The main difference was having a seperate control component and content component.
This is how I got it working:
>> app.module.ts
Note: saurav1405 suggested putting ModalContentComponent into declarations, (possibly a typo after reviewing his comments again).
but you need to put the actual modal custom modal components in here (in this case SasModalComponent & SasModalContent).
And the content component (SasModalContent) needs to be the entry component.
import { SasModalComponent, SasModalContent } from './sas-modal/sas-modal.component';
...
#NgModule({
declarations: [
AppComponent,
SasModalComponent,
SasModalContent
],
entryComponents: [SasModalContent],
...
>> app.component.html:
The ngbModalContainer declaration should be along side the component declaration in the parent component html template, not in the index.html, which I think was the main reason I was getting the errors posted in the question.
<template ngbModalContainer></template>
<sas-modal-component></sas-modal-component>
>> sas-modal.component.ts:
This file combines both the control component [sas-modal-component] (that opens the content / template) and the content component [sas-modal-content] (that has the reference to the active modal and modal template).
import {Component, Input, Compiler } from '#angular/core';
import {NgbModal, NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'sas-modal-content',
templateUrl: 'sas-modal-content.html'
})
export class SasModalContent {
#Input() name;
constructor(public activeModal: NgbActiveModal) { }
}
#Component({
selector: 'sas-modal-component',
templateUrl: 'sas-modal.component.html'
})
export class SasModalComponent {
constructor(private modalService: NgbModal, private compiler: Compiler) { }
open() {
//this.compiler.clearCacheFor(SasModalContent); //Only use when the template is caching when you don't want it to.
const modalRef = this.modalService.open(SasModalContent);
modalRef.componentInstance.name = 'World';
}
}
>> sas-modal.component.html: Contains the button / control to open the modal
<h2> Click the button to open the modal</h2>
<button class="btn btn-lg btn-outline-primary" (click)="open()">Launch demo modal</button>
>> sas-modal-content.html: Holds the modal template - can be whatever you want
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Hi there!</h4>
</div>
<div class="modal-body card-info">
<h3 style="color: white;">So nice to meet you</h3>
<h4 style="color: white;">This modal is great!</h4>
</div>
<div class="modal-footer ">
<button type="button" class="btn btn-secondary" (click)="activeModal.close('Close click')">Close</button>
</div>

Categories