How Do I use Angular 4 Dialog Directives? - angular-material2

I am developing an Angular web application using:
Angular 4.1.2
Angular Material 2.0.0-beta.11
I am trying to create a simple modal dialog and on reading the Angular guide documents (Dialog | Angular Material) I see that there are several directives available to make it easier to structure the dialog content.
I cannot work out how to implement md-dialog-title, <md-dialog-content>, <md-dialog-actions> or md-dialog-close. The attributes, when applied to an element, appear to make no difference at all and the <md-dialog-content> and <md-dialog-actions> create errors like this:
Unhandled Promise rejection: Template parse errors: 'md-dialog-content' is not a known element:
Any guidance would be very welcome please. Here are some further details of my project:
For my initial development I have created an Angular module, named AngularMaterialModule to manage my Angular Materials. Here is a summary of it:
import { NgModule } from '#angular/core';
import {
MdAutocompleteModule,
MdButtonModule,
....
MdStepperModule,
StyleModule,
} from '#angular/material';
import { CdkTableModule } from '#angular/cdk/table';
import { A11yModule } from '#angular/cdk/a11y';
import { BidiModule } from '#angular/cdk/bidi';
import { OverlayModule } from '#angular/cdk/overlay';
import { PlatformModule } from '#angular/cdk/platform';
import { ObserversModule } from '#angular/cdk/observers';
import { PortalModule } from '#angular/cdk/portal';
#NgModule({
exports: [
// Material Modules
MdAutocompleteModule,
MdButtonModule,
....
PlatformModule,
PortalModule
],
declarations: []
})
export class AngularMaterialModule { }
My Visual Studio Solution was created using dotnet new angular taking advantage of the Microsoft ASP.Net SPA Templates.
In my app.module.client.ts file I import the AngularMaterialModule, described above, like this:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { AngularMaterialModule } from './core/angular-material.module';
import { sharedConfig } from './app.module.shared';
#NgModule({
bootstrap: sharedConfig.bootstrap,
declarations: sharedConfig.declarations,
imports: [
BrowserModule,
BrowserAnimationsModule,
AngularMaterialModule,
FormsModule,
HttpModule,
...sharedConfig.imports
],
providers: [
{ provide: 'ORIGIN_URL', useValue: location.origin }
]
})
export class AppModule {
}

You need to import the actual dialog module into the module you want to use it in.
import { MdDialogModule } from '#angular/material';
#NgModule({
imports: [
MdDialogModule
],
})
After that, it's a straight forward and follow the example in their docs
import {Component, Inject} from '#angular/core';
import {MdDialog, MdDialogRef, MD_DIALOG_DATA} from '#angular/material';
/**
* #title Dialog Overview
*/
#Component({
selector: 'dialog-overview-example',
templateUrl: 'dialog-overview-example.html'
})
export class DialogOverviewExample {
animal: string;
name: string;
constructor(public dialog: MdDialog) {}
openDialog(): void {
let dialogRef = this.dialog.open(DialogOverviewExampleDialog, {
width: '250px',
data: { name: this.name, animal: this.animal }
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
this.animal = result;
});
}
}
#Component({
selector: 'dialog-overview-example-dialog',
templateUrl: 'dialog-overview-example-dialog.html',
})
export class DialogOverviewExampleDialog {
constructor(
public dialogRef: MdDialogRef<DialogOverviewExampleDialog>,
#Inject(MD_DIALOG_DATA) public data: any) { }
onNoClick(): void {
this.dialogRef.close();
}
}
If you ever want to create a custom dialog component, you will have to add it into your entryComponents in the module.
import { MdDialogModule } from '#angular/material';
#NgModule({
entryComponents: [
AddressDialogComponent,
],
imports: [
MdDialogModule,
],
exports: [
AddressDialogComponent,
],
})

Related

Problem with e2e testing with NestJS TestingModule, GraphQL code first and TypeOrm

I'm in struggle since few days with e2e testing my NestJS application using GraphQL code first approach and TypeOrm.
I'm trying to create a TestingModule by injecting nestjs GraphQLModule with autoSchemaFile and I'm always getting the error "Schema must contain uniquely named types but contains multiple types named ...".
Here a reproduction of my bug with minimal code:
character.entity.ts:
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
import { ObjectType, Field, ID } from 'type-graphql';
#Entity()
#ObjectType()
export class Character {
#PrimaryGeneratedColumn()
#Field(() => ID)
id: string;
#Column({ unique: true })
#Field()
name: string;
}
character.resolver.ts:
import { Query, Resolver } from '#nestjs/graphql';
import { Character } from './models/character.entity';
import { CharacterService } from './character.service';
#Resolver(() => Character)
export class CharacterResolver {
constructor(private readonly characterService: CharacterService) {}
#Query(() => [Character], { name: 'characters' })
async getCharacters(): Promise<Character[]> {
return this.characterService.findAll();
}
}
character.module.ts:
import { Module } from '#nestjs/common';
import { CharacterResolver } from './character.resolver';
import { CharacterService } from './character.service';
import { TypeOrmModule } from '#nestjs/typeorm';
import { Character } from './models/character.entity';
#Module({
imports: [TypeOrmModule.forFeature([Character])],
providers: [CharacterResolver, CharacterService],
})
export class CharacterModule {}
app.module.ts:
import { Module } from '#nestjs/common';
import { CharacterModule } from './character/character.module';
import { TypeOrmModule } from '#nestjs/typeorm';
import { Connection } from 'typeorm';
import { GraphQLModule } from '#nestjs/graphql';
#Module({
imports: [TypeOrmModule.forRoot(), GraphQLModule.forRoot({ autoSchemaFile: 'schema.gql' }), CharacterModule],
controllers: [],
providers: [],
})
export class AppModule {
constructor(private readonly connection: Connection) {}
}
and finally: character.e2e-spec.ts:
import { INestApplication } from '#nestjs/common';
import { Test, TestingModule } from '#nestjs/testing';
import { TypeOrmModule } from '#nestjs/typeorm';
import { CharacterModule } from '../src/character/character.module';
import { GraphQLModule } from '#nestjs/graphql';
describe('CharacterResolver (e2e)', () => {
let app: INestApplication;
beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
TypeOrmModule.forRoot(),
GraphQLModule.forRoot({ playground: false, autoSchemaFile: 'schema.gql' }),
CharacterModule,
],
}).compile();
app = module.createNestApplication();
await app.init();
});
it('should create testing module', () => {
expect(1).toBe(1);
});
afterAll(async () => {
await app.close();
});
});
And after running npm run test:e2e:
Schema must contain uniquely named types but contains multiple types named "Character".
at typeMapReducer (../node_modules/graphql/type/schema.js:262:13)
at Array.reduce (<anonymous>)
at new GraphQLSchema (../node_modules/graphql/type/schema.js:145:28)
at Function.generateFromMetadataSync (../node_modules/type-graphql/dist/schema/schema-generator.js:31:24)
at Function.<anonymous> (../node_modules/type-graphql/dist/schema/schema-generator.js:16:33)
at ../node_modules/tslib/tslib.js:110:75
at Object.__awaiter (../node_modules/tslib/tslib.js:106:16)
at Function.generateFromMetadata (../node_modules/type-graphql/dist/schema/schema-generator.js:15:24)
I don't find any other way to create a testing module with graphql code first approach on official doc or while googling... Am I missing something ?
Your ormconfig.json need to look like this:
"entities": [
"src/**/*.entity.js"
],
"migrations": [
"src/migration/*.js"
],
"cli": {
"migrationsDir": "src/migration"
}
I.e you need to specify the entities being in the src, not dist folder. If not TypeGraphQL will generate the schema for each resolver twice. To get the generate and run migration commands to work you would have to setup a different ormconfig.json for your development environment.

Nativescript + angular : blank page on tab view after upgrading to 8.2.0 without any error

Environment
CLI: 6.0.3
Cross-platform modules:6.0.0
Android Runtime:6.0.2
iOS Runtime:6.0.2
Plugin(s):
NativeScript-Angular:8.2.0
Angular:8.2.0
After upgrading to the latest cli and nativescript-angular I get a blank white screen when I start the app which opens the page tab based, but when I try to output something using the component ts file I can get it on the console. The problem is only at the template level (I get a blank page).
this is my app.modules.ts file:
import { NgModule, NO_ERRORS_SCHEMA } from "#angular/core";
import { CoreModule } from "./core/core.module";
import { SharedModule } from "./shared/shared.module";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { NativeScriptCommonModule } from "nativescript-angular/common";
import { TNSImageModule } from 'nativescript-image/angular';
import * as applicationModule from "tns-core-modules/application";
import * as imageModule from "nativescript-image";
declare var GMSServices: any;
if (applicationModule.android) {
applicationModule.on(applicationModule.launchEvent, () => {
console.log('initialize pipeline');
imageModule.initialize();
});
} else {
GMSServices.provideAPIKey("*********");
}
// Uncomment and add to NgModule imports if you need to use two-way binding
// import { NativeScriptFormsModule } from "nativescript-angular/forms";
// Uncomment and add to NgModule imports if you need to use the HttpClient wrapper
// import { NativeScriptHttpClientModule } from "nativescript-angular/http-client";
#NgModule({
bootstrap: [AppComponent],
imports: [NativeScriptCommonModule, CoreModule, SharedModule, TNSImageModule, AppRoutingModule],
declarations: [AppComponent],
providers: [],
schemas: [NO_ERRORS_SCHEMA]
})
/*
Pass your application module to the bootstrapModule function located in main.ts to start your app
*/
export class AppModule {}
this is the app-routing.modules.ts
import { NgModule } from "#angular/core";
import { NativeScriptRouterModule } from "nativescript-angular/router";
//import { hasKey } from "tns-core-modules/application-settings";
import { Routes } from "#angular/router";
//const homePath = (hasKey('skipLoginScreen') ? 'home/tabs':'auth/login');
const routes: Routes = [
{
path: "",
redirectTo: "home",
pathMatch: "full"
},
{
path: "home",
loadChildren: "~/app/home/home.module#HomeModule"
},
{
path: "products",
loadChildren: "~/app/products/products.module#ProductsModule"
},
{
path: "auth",
loadChildren: "~/app/auth/auth.module#AuthModule"
},
{
path: "account",
loadChildren: "~/app/account/account.module#AccountModule"
},
{
path: "cart",
loadChildren: "~/app/cart/cart.module#CartModule"
}
];
#NgModule({
imports: [NativeScriptRouterModule.forRoot(routes, { enableTracing: true } )],
exports: [NativeScriptRouterModule]
})
export class AppRoutingModule {}
this is my home-routing.module.ts:
import { NgModule } from "#angular/core";
import { Routes } from "#angular/router";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { TabsComponent } from "./tabs.component";
import { HomeComponent } from "./home-tab/home.component";
import { CategoriesComponent } from "./categories-tab/categories.component";
import { InfoComponent } from "./info-tab/info.component";
import { LocationsComponent } from "./locations-tab/locations.component";
import { AccountComponent } from "./account-tab/account.component";
export const COMPONENTS = [TabsComponent, HomeComponent, CategoriesComponent, InfoComponent, LocationsComponent, AccountComponent];
const routes: Routes = [
{
path: "",
redirectTo: "tabs",
pathMatch: "full"
},
{
path: "tabs",
component: TabsComponent,
children: [{ path: "home", component: HomeComponent, outlet: "homeTab" }, { path: "categories", component: CategoriesComponent, outlet: "categoriesTab" }, { path: "info", component: InfoComponent, outlet: "infoTab" }, { path: "locations", component: LocationsComponent, outlet: "locationsTab" }, { path: "account", component: AccountComponent, outlet: "accountTab" }]
}
];
#NgModule({
imports: [NativeScriptRouterModule.forChild(routes)],
exports: [NativeScriptRouterModule]
})
export class HomeRoutingModule {}
this is my home.module.ts:
import { NgModule, NO_ERRORS_SCHEMA } from "#angular/core";
import { HomeRoutingModule, COMPONENTS } from "./home-routing.module";
import { SharedModule } from "../shared/shared.module";
import { PushNotificationsService } from './../core/services/push-notifications.service';
// Uncomment and add to NgModule imports if you need to use two-way binding
// import { NativeScriptFormsModule } from "nativescript-angular/forms";
// Uncomment and add to NgModule imports if you need to use the HttpClient wrapper
// import { NativeScriptHttpClientModule } from "nativescript-angular/http-client";
#NgModule({
imports: [SharedModule, HomeRoutingModule],
providers: [PushNotificationsService],
declarations: [...COMPONENTS],
schemas: [NO_ERRORS_SCHEMA]
})
/*
Pass your application module to the bootstrapModule function located in main.ts to start your app
*/
export class HomeModule {}
this is my tabs.component.ts:
import { Component, OnInit } from "#angular/core";
import { Page } from "tns-core-modules/ui/page";
import { RouterExtensions } from "nativescript-angular/router";
import { DataService } from "../core/services/data.service";
import { ActivatedRoute } from "#angular/router";
#Component({
selector: "tabs",
moduleId: module.id,
templateUrl: "./tabs.component.html"
})
export class TabsComponent implements OnInit {
selectedIndex: number = 4;
constructor(private page: Page, private activeRoute: ActivatedRoute, private dataService: DataService, private routerExt: RouterExtensions) {}
ngOnInit(): void {
this.page.actionBarHidden = true;
this.routerExt.navigate([{ outlets: { homeTab: ["home"], infoTab: ["info"], categoriesTab: ["categories"], accountTab: ["account"], locationsTab: ["locations"] } }], { relativeTo: this.activeRoute });
this.dataService.getActivatedTab().subscribe(index => {
this.selectedIndex = index;
});
}
onTabChanged(args) {
setTimeout(() => {
this.dataService.setActivatedTab(args.newIndex);
}, 30);
}
}

Jasmine testcase for angular2 router.navigate()

I am having a app.component.html file with button to navigate to another component called HomeComponent
<button (click)="nav()" id="nav">Navigate</button>
<router-outlet></router-outlet>
My app.component.ts file
import { Component } from '#angular/core';
import { RouterModule,Router, Routes } from '#angular/router';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
constructor(private router: Router){
}
nav(){
this.router.navigate(['/home']);
}
}
and my app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { RouterModule, Routes,Router } from '#angular/router';
#NgModule({
declarations: [
AppComponent,
HomeComponent
],
imports: [
BrowserModule,
RouterModule.forRoot([{ path: "", component: AppComponent}]),
RouterModule.forChild([{ path: "home", component: HomeComponent}])
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Here is my spec file app.component.spec.ts
import { TestBed, async, ComponentFixture, fakeAsync, tick,inject } from '#angular/core/testing';
import { By, BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { DebugElement } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { Router, RouterOutlet } from "#angular/router";
import { FormsModule } from "#angular/forms";
import { RouterTestingModule } from '#angular/router/testing';
import * as br from '#angular/platform-browser';
describe('Component:AppComponent', () => {
let location, router;
let mockRouter
beforeEach(() => {
mockRouter = {
navigate: jasmine.createSpy('navigate')
};
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes([
{ path: 'home', component: HomeComponent }
])],
declarations: [AppComponent, HomeComponent]
});
});
it('should go home', async(() => {
let fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
console.log(mockRouter.navigate);
let component = TestBed.createComponent(AppComponent).componentInstance;
component.nav();
spyOn(component, 'nav');
fixture.detectChanges();
expect(mockRouter.navigate).toHaveBeenCalledWith(['/home']);
}));
});
I am getting the result as
In order to create unit test case for router.navigate you can do something like this:
import { TestBed, async, ComponentFixture, fakeAsync, tick,inject } from '#angular/core/testing';
import { By, BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { DebugElement } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { Router, RouterOutlet } from "#angular/router";
import { FormsModule } from "#angular/forms";
import { RouterTestingModule } from '#angular/router/testing';
import * as br from '#angular/platform-browser';
describe('Component:AppComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [AppComponent, HomeComponent]
});
});
it('should go home', async(inject([Router], (router) => {
spyOn(router, 'navigate'); //added a spy on router
let fixture = TestBed.createComponent(AppComponent);
let component = TestBed.createComponent(AppComponent).componentInstance;
component.nav();
expect(router.navigate).toHaveBeenCalled();
expect(router.navigate).toHaveBeenCalledWith(['/home']);
}));
});
You have spied on router but you haven't provided it to the testBed environment. Try adding
providers: [
{ provide: Router, useValue: mockRouter},
],
after declarations.
Also you need not include RouterTestingModule since you are not clicking any links.
References:
https://stackoverflow.com/a/46342813/8558515
Angular 2 Unit Testing - Cannot read property 'root' of undefined

kendo ui for angular AutoComplete wont open

iam trying to use the autocomplete component
data is loaded (i can see it on the HTML)
but when user types inside the textbox
nothing happens
any idea why ?
thank u
the HTML:
<kendo-autocomplete [data]="data"
[placeholder]="'e.g. Denmark'"
class="countries" >
</kendo-autocomplete>
the TS:
import { Component, OnInit, NgModule } from '#angular/core';
#Component({
selector: 'app-product-search-box',
templateUrl: './product-search-box.component.html',
styleUrls: ['./product-search-box.component.css']
})
export class ProductSearchBoxComponent implements OnInit {
public data: Array<string> = ["Albania", "Andorra", "Armenia", "Austria", "Azerbaijan"];
constructor() {
}
ngOnInit() {
}
}
proof that data is loaded:
Make sure you have imported the BrowserAnimationsModule required for the popup animations:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { BrowserAnimationsModule } from '#angular/platformbrowser/animations';
import { HttpModule } from '#angular/http';
import { DropDownsModule } from '#progress/kendo-angular-dropdowns';
import 'hammerjs';
import { AppComponent } from './app.component';
#NgModule({
imports: [ BrowserModule, BrowserAnimationsModule, HttpModule,
DropDownsModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Everything in the provided code seems fine otherwise. You should also check for console errors like already suggested.
Here is an working example:
EXAMPLE

error using isBrowser function in angular universal

I'm trying to use the isBrowser function in angular universal but I keep getting the same error when I build. I did install the npm package of angular-universal
npm i angular2-universal --save
'ng build -prod -aot'
ERROR in Illegal state: symbol without members expected, but got {"filePath":"C:/dir/universal/website/node_modules/#angular/platform-browser/platform-browser.d.ts","name":"__platform_browser_private__","members":["BROWSER_SANITIZATION_PROVIDERS"]}.
ERROR in ./src/main.ts
Module not found: Error: Can't resolve './$$_gendir/app/app.module.ngfactory' in 'C:/dir/universal/website\src'
# ./src/main.ts 4:0-74
# multi ./src/main.ts
this is my app.module.ts:
//modules
import { HomeModule } from './home/home.module';
import { IntakeFormulierModule } from './intake-formulier/intake-formulier.module';
import { BrowserModule } from '#angular/platform-browser';
import { UniversalModule } from 'angular2-universal/browser';
import { NgModule } from '#angular/core';
//routing
import { routing } from "./app.routing";
//pages
import { AppComponent } from './app.component';
//isbrowser
import { isBrowser } from 'angular2-universal';
#NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule.withServerTransition({
appId: 'website-u - (starter)'
}),
HomeModule,
IntakeFormulierModule,
routing,
],
providers: [
{ provide: 'isBrowser', useValue: isBrowser }
],
bootstrap: [AppComponent]
})
export class AppModule { }
this is my app/home/landing/landing.ts
import { Component, Inject } from '#angular/core';
import { Router } from '#angular/router';
#Component({
...
})
export class LandingComponent {
constructor(//public updateTop: TopImageUpdateService,
public router: Router,
#Inject('isBrowser') public isBrowser: boolean) {}
navigateToResults(name) {
if (this.isBrowser) {
let scrollToTop = window.setInterval(() => {
let pos = window.pageYOffset;
if (pos > 0) {
window.scrollTo(0, pos - 10); // how far to scroll on each step
} else {
window.clearInterval(scrollToTop);
this.router.navigate(['home/page', name]);
}
}, 9)
}
}
}
It looks like they are using isPlatformBrowser() instead of isBrowser() in the angular universal example.
https://github.com/angular/universal#universal-gotchas
import { Component, Inject, PLATFORM_ID, OnInit } from '#angular/core';
import { isPlatformBrowser, isPlatformServer } from '#angular/common';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements {
constructor(
#Inject(PLATFORM_ID) private platformId: Object
){
}
ngOnInit(){
if (isPlatformBrowser(this.platformId)) {
//Client only code.
} else {
//Server only code.
}
}
}

Resources