I tried splitting the Angular Dart app layout example to different components but the drawer toggle function is unreachable. When the same code is on one file. The toggle function is reachable.
Original File Content
parent.html
<drawer #drawer="drawer"></drawer>
<div class="material-content">
<navigation (toggleState)="drawer.toggle()"></navigation>
<content></content>
</div>
parent.dart
import 'package:angular/angular.dart';
import 'package:console/src/components/navigation/navigation.dart';
import 'package:console/src/components/drawer/drawer.dart';
#Component(
selector: 'dashboard-layout',
styleUrls: [
'dashboard_layout.css',
],
templateUrl: 'dashboard_layout.html',
directives: [
Drawer,
Navigation,
]
)
class DashboardLayout implements OnInit {
#override
Future<Null> ngOnInit() {
return null;
}
toggleDrawer () {
drawerVisible = !drawerVisible;
print(drawerVisible);
}
}
drawer.html
<material-drawer persistent>
<material-list *deferredContent>
<div group class="mat-drawer-spacer"></div>
<div group>
<material-list-item>
<material-icon icon="inbox"></material-icon>Inbox
</material-list-item>
<material-list-item>
<material-icon icon="star"></material-icon>Star
</material-list-item>
<material-list-item>
<material-icon icon="send"></material-icon>Sent Mail
</material-list-item>
<material-list-item>
<material-icon icon="drafts"></material-icon>Drafts
</material-list-item>
</div>
<div group>
<div label>Tags</div>
<material-list-item>
<material-icon icon="star"></material-icon>Favorites
</material-list-item>
</div>
</material-list>
drawer.dart
import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';
#Component(
selector: 'drawer',
styleUrls: [
'drawer.css',
'package:angular_components/app_layout/layout.scss.css'
],
templateUrl: 'drawer.html',
directives: [
DeferredContentDirective,
MaterialListComponent,
MaterialListItemComponent,
MaterialPersistentDrawerDirective,
MaterialIconComponent,
]
)
class Drawer extends MaterialDrawerBase implements OnInit {
bool customWidth = false;
bool end = false;
Drawer() : super(visible: true) {
}
#override
Future<Null> ngOnInit() {
return null;
}
}
navigation.dart
import 'dart:async';
import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';
import 'package:console/src/components/avatar/avatar.dart';
import 'package:angular_components/laminate/overlay/zindexer.dart';
#Component(
selector: 'navigation',
styleUrls: [
'navigation.css',
'package:angular_components/app_layout/layout.scss.css'
],
templateUrl: 'navigation.html',
directives: [
PopupSourceDirective,
MaterialIconComponent,
MaterialButtonComponent,
MaterialToggleComponent,
MaterialPopupComponent,
DeferredContentDirective,
MaterialPersistentDrawerDirective,
Avatar,
],
providers: [popupBindings, ClassProvider(ZIndexer)],
)
class Navigation implements OnInit {
bool visible = false;
final _toggleRequest = StreamController();
Iterable<RelativePosition> avatarPopupPositions = [
RelativePosition.AdjacentBottomRight
];
#Output()
Stream get toggleState => _toggleRequest.stream;
void toggleDrawer() {
_toggleRequest.add(null);
}
#override
Future<Null> ngOnInit() {
return null;
}
}
navigation.html
<header class="material-header shadow">
<div class="material-header-row">
<material-button icon
class="material-drawer-button" (trigger)="toggleDrawer()">
<material-icon icon="menu"></material-icon>
</material-button>
<span class="material-header-title">Console</span>
<div class="material-spacer"></div>
<avatar [userName]="'Someone Awesome'"
popupSource
#source="popupSource"
(trigger)="visible = !visible">
</avatar>
<material-popup
[source]="source" [(visible)]="visible"
[enforceSpaceConstraints]="true"
[preferredPositions]="avatarPopupPositions">
<div style="width: 256px; height: 200px">
Hello, Hello, Hello, Hello.
</div>
</material-popup>
</div>
</header>
Error
[error] The method 'toggle' isn't defined for the class 'Element'.
(package:console/src/layouts/parent/parent.template.dart, line 336, col 18)
So why is #drawer="drawer" An AngularDart Component with the toggle function when everything is in one file but it is a HTML Element when it is split.
The drawer is actually using the exportAs of the drawer component here: https://github.com/dart-lang/angular_components/blob/7f254c89cbbd512cc284a7e9d03bb687f9948bd9/angular_components/lib/app_layout/material_temporary_drawer.dart#L15
It really shouldn't be needed for the component, but we wanted the directive and the component to work the same way.
You would either need to add the exportAs="drawer" or just use the #drawer syntax without using #drawer="drawer"
Related
I am trying to integrate the angular-calendar context menu from here..
https://mattlewis92.github.io/angular-calendar/#/context-menu on of the child module called Calendar integrates it.
after installing all necessary module, the context-menu not working for me.
here is my child module :
import { NgModule } from '#angular/core';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { HttpClientModule } from "#angular/common/http";
import { CalendarModule, DateAdapter } from 'angular-calendar';
import { ContextMenuModule } from 'ngx-contextmenu';
import { adapterFactory } from 'angular-calendar/date-adapters/date-fns';
import { CommonModule } from '#angular/common';
import { RouterModule, Routes } from '#angular/router';
import { StoreModule } from '#ngrx/store';
import { EffectsModule } from '#ngrx/effects';
import { reducerCalendar } from "./state/calendar.reducer";
import { EffectsEvents } from "./state/calendar.effects";
import { IboCalendarComponent } from './components/ibo-calendar/ibo-calendar.component';
import { IboCalendarHeaderComponent } from './ibo-calendar-header/ibo-calendar-header.component';
import { CalendarShellComponent } from './containers/calendar-shell/calendar-shell.component';
import { SharedModule } from "./../shared-components/shared.module";
const iboCalenderRoutes: Routes = [
// { path: '', redirectTo:'setupConfig', pathMatch:'full' },
{ path: 'iboCalendar', component: CalendarShellComponent }
];
#NgModule({
declarations: [IboCalendarComponent, IboCalendarHeaderComponent, CalendarShellComponent],
imports: [
CommonModule,
BrowserAnimationsModule,
HttpClientModule,
SharedModule,
CalendarModule.forRoot({
provide: DateAdapter,
useFactory: adapterFactory
}),
ContextMenuModule.forRoot({
useBootstrap4: true
}),
RouterModule.forChild(iboCalenderRoutes),
EffectsModule.forFeature([EffectsEvents]),
StoreModule.forFeature('reducerCalendar', reducerCalendar)
],
exports: [ ]
})
export class iboCalendarModule { }
here is the ts file :
import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges } from '#angular/core';
import { CalendarService } from "./../../services/calendar.service";
import { ModelEvent, EventState } from "./../../models/model.event";
import { CalendarEvent } from 'angular-calendar';
import { Observable, Subject } from 'rxjs';
import { colors } from "./../../utilities/colors";
import { tap } from 'rxjs/operators';
declare var $:any;
#Component({
selector: 'ibo-calendar',
templateUrl: './ibo-calendar.component.html',
styleUrls: ['./ibo-calendar.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class IboCalendarComponent implements OnChanges,OnInit {
view: string = 'month';
// viewDate: Date = new Date('August 19, 2018');
viewDate: Date = new Date()
#Input() events:ModelEvent[];
#Input() currentEvent: ModelEvent;
refresh: Subject<any> = new Subject();
constructor() { }
ngOnInit() {
const headerHeight = $('.site-header').outerHeight();
//moving content down to header
$('body').css({paddingTop: headerHeight});
}
ngOnChanges() {
if( this.currentEvent ) {
this.viewDate = new Date(this.currentEvent.start);
}
}
eventClicked({ event }: { event: CalendarEvent }): void {
console.log('Event clicked', event);
}
addEvent(date:Date):void {
console.log('date is', date);
this.events.push({
id : 0,
start : date,
title : 'New Event',
end : new Date(),
allDay : false
})
this.refresh.next();
}
}
here is the template file :
<div class="container-fluid site-content">
<ibo-calendar-header [(view)]="view" [(viewDate)]="viewDate"></ibo-calendar-header>
<context-menu #basicMenu>
<ng-template contextMenuItem (execute)="addEvent($event.item)">
Add event
</ng-template>
</context-menu>
<ng-template
#monthCellTemplate
let-day="day"
let-openDay="openDay"
let-locale="locale"
let-tooltipPlacement="tooltipPlacement"
let-highlightDay="highlightDay"
let-unhighlightDay="unhighlightDay"
let-eventClicked="eventClicked"
>
<div
class="fill-height"
[contextMenu]="basicMenu"
[contextMenuSubject]="day.date"
>
<div class="cal-cell-top">
<span class="cal-day-badge" *ngIf="day.badgeTotal > 0"
>{{ day.badgeTotal }}</span
>
<span class="cal-day-number"
>{{ day.date | calendarDate:'monthViewDayNumber':locale }}</span
>
</div>
<div class="cal-events">
<div
class="cal-event"
*ngFor="let event of day.events"
[style.backgroundColor]="event.color.primary"
[ngClass]="event?.cssClass"
(mouseenter)="highlightDay.emit({event: event})"
(mouseleave)="unhighlightDay.emit({event: event})"
[mwlCalendarTooltip]="event.title | calendarEventTitle:'monthTooltip':event"
[tooltipPlacement]="tooltipPlacement"
(click)="$event.stopPropagation(); eventClicked.emit({event: event})"
></div>
</div>
</div>
</ng-template>
<ng-template
#weekHeaderTemplate
let-days="days"
let-locale="locale"
let-dayHeaderClicked="dayHeaderClicked"
>
<div class="cal-day-headers">
<div
class="cal-header"
*ngFor="let day of days"
[class.cal-past]="day.isPast"
[class.cal-today]="day.isToday"
[class.cal-future]="day.isFuture"
[class.cal-weekend]="day.isWeekend"
(click)="dayHeaderClicked.emit({day: day})"
[contextMenu]="basicMenu"
[contextMenuSubject]="day.date"
>
<b>{{ day.date | calendarDate:'weekViewColumnHeader':locale }}</b><br />
<span
>{{ day.date | calendarDate:'weekViewColumnSubHeader':locale }}</span
>
</div>
</div>
</ng-template>
<ng-template #dayHourSegmentTemplate let-segment="segment" let-locale="locale">
<div
class="cal-hour-segment"
[ngClass]="segment.cssClass"
[contextMenu]="basicMenu"
[contextMenuSubject]="segment.date"
>
<div [hidden]="!segment.isStart" class="cal-time">
{{ segment.date | calendarDate:'dayViewHour':locale }}
</div>
</div>
</ng-template>
<div class="alert alert-info">
Click on a day on the view.
<strong *ngIf="clickedDate">You clicked on this day: {{ clickedDate | date:'medium' }}</strong>
</div>
<div>
<div [ngSwitch]="view">
<mwl-calendar-month-view *ngSwitchCase="'month'" [viewDate]="viewDate"
[events]="events" (eventClicked)="eventClicked($event)" (dayClicked)="clickedDate = $event.day.date">
</mwl-calendar-month-view>
<mwl-calendar-week-view *ngSwitchCase="'week'"
[viewDate]="viewDate" [events]="events" (eventClicked)="eventClicked($event)" (dayHeaderClicked)="clickedDate = $event.day.date">
</mwl-calendar-week-view>
<mwl-calendar-day-view *ngSwitchCase="'day'"
[viewDate]="viewDate" [events]="events" (eventClicked)="eventClicked($event)">
</mwl-calendar-day-view>
</div>
</div>
</div>
Getting no errors as well.
any one guide me? thanks in advance.
app.component.ts
import { Component,OnInit } from '#angular/core';
import {FormControl,FormGroup,FormArray,FormBuilder} from '#angular/forms'
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular 6';
form=new FormGroup({
topics:new FormArray([])
})
addTopic(topic:HTMLInputElement){
(this.form.get('topics') as FormArray).push(new FormControl(topic.value));
topic.value='';
}
}
app.component.html
<form>
<input type="text" class="form-control" (keyup.enter)="this.addTopic(topic)" #topic />
<ul class="list-group">
<li class="list-group-item" *ngFor="let topic of form.get('topics').controls">
{{topic.value}}
</li>
</ul>
</form>
I have created a Multi Input Control using Angular FormArray but how can i Validate the same for Minimum 2 Items(Length=2) and only accept integer values.
How to Add Validators.minlength like Reactive Form / Model Driven Form Approach.
How can i get those items using ngModel?
I hope this helps.
import {
Component,
OnInit
} from '#angular/core';
import {
FormControl,
FormGroup,
FormArray,
FormBuilder
} from '#angular/forms'
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular 6';
form = new FormGroup({
topics: new FormArray(this.formBuilder.control(''), [Validators.reqired, Valiadtors.minlength(2)], Validators.Paterrn("^[0-9]*$"))
])
addTopic(topic: HTMLInputElement) {
(this.form.get('topics') as FormArray).push(new FormControl(topic.value));
topic.value = '';
}
}
import { Component, Input } from "#angular/core";
import "./loadingSpinner.component.css!";
#Component({
selector: "loading-spinner-Parent",
template: `
<div *ngIf="showSpinner" class="loader-directive-wrapper">
<div class="loader"></div>
</div>`
})
export class LoadingSpinnerComponent {
#Input() public showSpinner: boolean = false;
}
Refreshing angular2 dart page using HashLocationStrategy works fine as it opens the exact same view.
Refreshing the page using PathLocationStrategy - with tomcat server configured to serve index.html - works for the url without parameter but does not work for the url with parameter.
localhost:8090/menu1 // refresh works
localhost:8090/menu2/paramVal // does not refresh
tomcat web.xml has
<error-page>
<error-code>404</error-code>
<location>/index.html</location>
</error-page>
main.dart
main() {
bootstrap(AppComponent, [
ROUTER_PROVIDERS,
provide(APP_BASE_HREF, useValue: '/')]);
}
app_component.dart
import 'package:angular2/core.dart';
import 'package:angular2/router.dart';
import 'package:angular2/angular2.dart';
import 'package:mboxes/menu1.dart';
import 'package:mboxes/menu2.dart';
#Component(
selector: 'my-app',
templateUrl: 'app_component.html',
directives: const [ROUTER_DIRECTIVES],
providers: const[ROUTER_PROVIDERS, ])
#RouteConfig(const [
const Route(
path: '/menu1',
name: 'Menu1',
component: Menu1Component,
useAsDefault: true),
const Route(
path: '/menu2/:param', name: 'Menu2', component: Menu2Component)
])
class AppComponent {}
app_component.html
<div class="container">
<nav>
<ul>
<li>
<a [routerLink]="['Menu1']">Menu1</a>
</li>
<li> <a [routerLink]="['Menu2', {'param':'paramVal'}]">Menu2</a> </li>
</ul>
</nav>
<div style="padding-left: 200px; padding-top: 200px; padding-bottom: 50px">
<router-outlet></router-outlet>
</div>
</div>
menu1.dart
import 'package:angular2/core.dart';
import 'package:angular2/router.dart';
#Component(
selector: 'menu1',
template: ''' menu 1 was clicked '''
)
class Menu1Component {}
menu2.dart
import 'package:angular2/core.dart';
import 'package:angular2/router.dart';
#Component(
selector: 'menu2',
template: ''' menu 2 was clicked'''
)
class Menu2Component implements OnInit {
final RouteParams _routeParams;
Menu2Component(this._routeParams);
ngOnInit() {
var val = _routeParams.get('param');
print ("passed param is " + val);
}
}
Instead of using 404 to serve index.html I think you want to set up a servlet-mapping with something like <url-pattern>*</url-pattern>
See also Tomcat servlet, redirect all urls to a single webpage
I am doing authentication and authorization of pages on the server side. on index pages of each controller. But inside each index page I want to use angular 2 hence I want to use angular 2 routing.
I have tried like
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template:''
})
export class AppComponent {
}
app.module.ts
import {NgModule} from '#angular/core';
import {BrowserModule} from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { RouterModule } from '#angular/router'
import { TestSuiteComponent } from './testsuite/testsuite.component'
//import {InputTextModule, CalendarModule, DataTable} from 'primeng/primeng';
import { DataTableModule, SharedModule } from 'primeng/primeng';
#NgModule({
imports: [BrowserModule, DataTableModule, SharedModule, RouterModule.forRoot([
{
path: 'TestSuiteEditor/Index',
component: TestSuiteComponent
},
{
path: 'Home/Index',
component: TestSuiteComponent
}
])],
declarations: [AppComponent,TestSuiteComponent],
bootstrap: [ AppComponent]
})
export class AppModule { }
on testsuite.component.ts page
import { Directive, Component, OnInit } from '#angular/core';
import {DataTableModule, SharedModule} from 'primeng/primeng';
import { TestSuite } from './testsuite';
#Component({
// moduleId: module.id,
selector: 'testsuite-header',
template: `
<div class="ui-widget-header ui-helper-clearfix" style="padding:4px 10px;border-bottom: 0 none">
<i class="fa fa-search" style="float:left;margin:4px 4px 0 0"></i>
<input #gb type="text" pInputText size="50" style="float:left" placeholder="Global Filter">
</div>
<div class="ui-datatable ui-widget">
<div class="ui-datatable-tablewrapper">
<p-dataTable [value]="testSuites" [rows]="5" [paginator]="true" [globalFilter]="gb" [editable]="true">
<p-column field="testSuiteId" header="TestSuites (startsWith)" [style]="{'width':'10%'}" [filter]="true" [editable]="true"></p-column>
<p-column field="projectId" header="ProjectId (contains)" [style]="{'width':'10%'}" [filter]="true" filterMatchMode="contains" [editable]="true"></p-column>
<p-column field="name" header="Name (startsWith)" [style]="{'width':'30%'}" [filter]="true" [editable]="true"></p-column>
<p-column field="description" header="Description (endsWith)" [style]="{'width':'40%'}" [filter]="true" filterMatchMode="endsWith" [editable]="true"></p-column>
<p-column field="isActive" header="IsActive (endsWith)" [style]="{'width':'10%'}" [filter]="true" filterMatchMode="endsWith" [editable]="true"></p-column>
</p-dataTable>
</div>
</div> `,
// providers: [TestSuiteService]
})
export class TestSuiteComponent{}
Home/Index.cshtml
<testsuite-header>Loading....</testsuite-header>
but it throwing an error of
Cannot find primary outlet to load 'TestSuiteComponent'
You have forgotten to add router-outlet in your application. You can define router-outlet in AppComponent like this-
<router-outlet></router-outlet>
So your AppComponent will looks like this-
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template:`
<!-- Routed views go here -->
<router-outlet></router-outlet>
`
})
export class AppComponent {
}
I have found the solution, thanks for your help
I have created the path similar to my MVC routing and added in routing.ts.
Since angular 2routing have feature of loading the active url so it automatically loads the component which is assign to that URL.