Argument of type Event is not assignable to parameter of type PanGestureEventData - nativescript

I'm building an NativeScript app using angular flavor. In the HTML side I've tried to bind to an TouchEvent but this is the error that I've got.
Error message:
Argument of type 'Event' is not assignable to parameter of type 'PanGestureEventData'.
Type 'Event' is missing the following properties from type 'PanGestureEventData': deltaX, deltaY, state, view, and 4 more.ngtsc(2345)
component.html
<Label
class="content-drawer"
(pan)="onPanMoveContainer($event)"
alignSelf="center"
textAlignment="center"
[text]="'fa-window-minimize' | fonticon"
class="fa"
fontSize="20"
></Label>
component.ts
import { AfterViewInit, ChangeDetectorRef, Component, OnInit } from '#angular/core';
import { BottomSheetLayoutBaseComponent } from '#loyaltyversion2/xplat/features';
import { PanState } from '#loyaltyversion2/xplat/nativescript/utils';
import { PanGestureEventData, View } from '#nativescript/core';
#Component({
moduleId: module.id,
selector: 'app-bottom-sheet-layout',
templateUrl: './bottom-sheet-layout.component.html',
styleUrls: ['./bottom-sheet-layout.scss'],
})
export class BottomSheetLayoutComponent
extends BottomSheetLayoutBaseComponent
{
private currentContentTransitionY = 200;
constructor() {
super();
}
onPanMoveContainer(event: PanGestureEventData) {
// TODO: why can't we use TouchGestureEventData
this.moveContentToLocation(this.currentContentTransitionY + event.deltaY);
if (event.state === PanState.UP) {
this.currentContentTransitionY =
this.currentContentTransitionY + event.deltaY;
}
}
}
My workspace is generated using nx/xplat#^12.0.0 and my guess is that there should be some misconfiguration regarding my tsconfig or some linters that are setup by xplat app generator but I didn't change anything in those files. Any guesses?

The error indicates that there is a mixup between the event name and the function's expected parameter type.
If you want to use the pan event with the PanGestureEventData:
<Label
(pan)="onPanMoveContainer($event)"
></Label>
onPanMoveContainer(event: PanGestureEventData) {
}
If you want to use the touch event with the TouchGestureEventData:
<Label
(touch)="onTouchMoveContainer($event)"
></Label>
onTouchMoveContainer(event: TouchGestureEventData) {
}

I had to disable 'strictTemplates' option in 'compilerOptions' located in your 'tsconfig.js'

Related

angular 9 candeactivate not working although code seems to be fine and not throwing any error

Hello Guys I am new to Angular and learning the things using the following tutorial link. For some reason the canDeactivate route guard seem to not work. Any help would be appreciated as I tried checking many things but none worked. I have the latest angular CLI and there are not errors in my code and for some reason the canDeactivate function is not at all called during the route change.
I am applying the function on the CreateEmployee route so when I fill the form for createEmployee and I try to navigate to different route then it should kick in.
create-employee-component.html: In this, I have few form elements
<form #employeeForm = "ngForm" (ngSubmit)="saveEmployee()" [ngClass]="{'was-validated': employeeForm.submitted}" novalidate>
create-employee-component.ts
import { Component, OnInit, ViewChild } from '#angular/core';
import { NgForm } from '#angular/forms';
import { Department } from '../models/department.model';
import { BsDatepickerConfig } from 'ngx-bootstrap/datepicker';
import { Employee } from '../models/employee.model';
import { EmployeeService } from './employee.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-create-employee',
templateUrl: './create-employee.component.html',
styleUrls: ['./create-employee.component.css']
})
export class CreateEmployeeComponent implements OnInit {
#ViewChild('employeeForm') public createEmployeeForm: NgForm;
datePickerConfig: Partial<BsDatepickerConfig>;
previewPhoto = false;
create-employee-can-deactivate-guard.service.ts
import { Injectable } from '#angular/core';
import { CanDeactivate } from '#angular/router';
import { CreateEmployeeComponent } from './create-employee.component';
#Injectable()
export class CreateEmployeeCanDeactivateGuardService implements CanDeactivate<CreateEmployeeComponent>{
canDeactivate(component: CreateEmployeeComponent): boolean{
alert("HJEJJEJEJ");
if(component.createEmployeeForm.dirty)
{
return confirm('Are you sure you want to discard your changes?');
}
return true;
}
}
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { ListEmployeesComponent } from './employees/list-employees.component';
import { CreateEmployeeComponent } from './employees/create-employee.component';
import { CreateEmployeeCanDeactivateGuardService } from './employees/create-employee-can-deactivate-guard.service';
const routes: Routes = [
{path: 'list', component: ListEmployeesComponent},
{
path:'create',
component: CreateEmployeeComponent,
canDeactivate: [CreateEmployeeCanDeactivateGuardService]
},
{path: '', redirectTo:'/list', pathMatch:'full'}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [CreateEmployeeCanDeactivateGuardService]
})
export class AppRoutingModule { }
I feel everything is correct as per some of the other answers I found on the StackOverflow. Please let me know what am I doing wrong here. I have also posted my code here.
I finally found out what was the issue. After some time spending on the research I found out that in the navbar previously I was using the href element with the anchor tag hence the canDeactivate guard was not kicking in. Now I changed it to [routerLink]="['/list']" and the canDeactivate started working correctly.
Posting the answer as it may be useful for someone who is looking for solution:
Previous Navbar with the anchor tag and href element:
<a class="nav-link" href="list">List <span class="sr-only">(current)</span></a>
Changed Navbar with the anchor tag and routerLink which is working fine with the canDeactivate:
<a class="nav-link" [routerLink]="['/list']">List <span class="sr-only">(current)</span></a>
If in case you are looking for the whole code please check the question where I have mentioned all the code chunks related to canDeactivate guard.

Navigating from single page view to side-menu layout in ionic 4

I'd like to build an app using Ionic 4 that simplistically works the following way:
On-boarding page is shown with some images/text
After user clicked 'start' button, some flag onboarded=true is written into local-storage
User redirected to the main app view which is a ion-split-pane containing side-menu layout
Next time when user launches the app, I check if he/she already viewed on-boarding screen (by checking presence of onboarded var in storage) and if it is - I immediately redirect the user to the main app having side-menu layout as I mentioned, omitting on-boarding screen.
I started the project using ionic cli, based on side-menu template and to fulfill logic described above, I modified it the following way:
app.component.ts
import { Component } from '#angular/core';
import { Platform } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { Storage } from '#ionic/storage';
import { Router } from '#angular/router';
#Component({
selector: 'app-root',
template: '<router-outlet></router-outlet>',
})
export class AppComponent {
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private storage: Storage,
private router: Router
) {
this.initializeApp();
}
async initializeApp() {
await this.platform.ready();
this.statusBar.styleDefault();
this.splashScreen.hide();
const onboarded = await this.storage.get('onboarded');
if (onboarded) {
this.router.navigate(['main-app']);
} else {
this.router.navigate(['onboarding']);
}
}
}
onboarding.page.html
<ion-header>
<ion-toolbar>
<ion-title>onboarding</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
Welcome aboard!
<ion-button (click)="start()">Start app!</ion-button>
</ion-content>
onboarding.page.ts
import { Component } from '#angular/core';
import { Storage } from '#ionic/storage';
import { Router } from '#angular/router';
#Component({
selector: 'app-onboarding',
templateUrl: './onboarding.page.html',
styleUrls: ['./onboarding.page.scss'],
})
export class OnboardingPage {
constructor(
private storage: Storage,
private router: Router
) { }
start() {
this.storage.set('onboarded', true);
this.router.navigate(['main-app']);
}
}
main-app.page.html
<ion-app>
<ion-split-pane>
<ion-menu>
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-menu-toggle auto-hide="false" *ngFor="let p of appPages">
<ion-item [routerDirection]="'root'" [routerLink]="[p.url]">
<ion-icon slot="start" [name]="p.icon"></ion-icon>
<ion-label>
{{p.title}}
</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
</ion-content>
</ion-menu>
<ion-router-outlet main></ion-router-outlet>
</ion-split-pane>
</ion-app>
main-app.page.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-main-app',
templateUrl: './main-app.page.html',
styleUrls: ['./main-app.page.scss'],
})
export class MainAppPage {
public appPages = [
{
title: 'Home',
url: '/home',
icon: 'home'
},
{
title: 'List',
url: '/list',
icon: 'list'
}
];
constructor() { }
}
List and Home pages are just empty pages and their content is not important for this example
Problem is that main-app containing side menu and content is not working properly. I know that there is a problem in <ion-router-outlet main></ion-router-outlet>'s usage but couldn't find the right solution.
Does anyone have idea how to make it work?
Thanks!
Andrew.
try adding contentId="content" to your <ion-menu>
ie: <ion-menu contentId="content">
and also add id="content" to your <ion-router-outlet>
ie: <ion-router-outlet id="content" main>
i seem to remember something about the router-outlet not working without that.

TypeError: Cannot read property 'cartesianChart' of undefined in nativescript

i an new in nativescript. i try to learn chart in nativescript but it's give "TypeError: Cannot read property 'cartesianChart' of undefined" error.
home.componet.html
<RadCartesianChart tkExampleTitle tkToggleNavButton>
<CategoricalAxis tkCartesianHorizontalAxis></CategoricalAxis>
<LinearAxis tkCartesianVerticalAxis></LinearAxis>
<LineSeries tkCartesianSeries [items]="categoricalSource" categoryProperty="Country" valueProperty="Amount"></LineSeries>
home.component.ts
import { Component, OnInit,ViewChild,AfterViewInit ,ElementRef} from '#angular/core';
import { WebView, LoadEventData } from "ui/web-view";
import { ObservableArray } from "tns-core-modules/data/observable-array";
import{DataService} from "../data.service"
import{Country} from "../country"
#Component({
moduleId: module.id,
selector: 'app-home',
providers: [DataService],
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
private _categoricalSource: ObservableArray<Country>;
constructor(private _dataService: DataService) { }
get categoricalSource(): ObservableArray<Country> {
return this._categoricalSource;
}
ngOnInit() {
this._categoricalSource = new ObservableArray(this._dataService.getCategoricalSource());
}
}
I was facing the same issue and solved it by removing the android platform and adding it again.
tns platform remove android
tns platform add android

NativeScript custom component not showing when using #wwwalkerrun/nativescript-ngx-magic

I create a new test app
> ng new TestApp
Then I install the nativescript-ngx-magic
> npm i #wwwalkerrun/nativescript-ngx-magic --save
Then create a new app.component.tns.html
<ActionBar title="Magic!" icon="" class="action-bar">
</ActionBar>
<StackLayout class="p-20">
<Label text="NativeScript is Neat." class="h1 text-center"></Label>
</StackLayout>
Create a blank app.component.tns.css
Then change my app.component.ts so that it will work with the nativescript-ngx-magic:
import { Component } from '#wwwalkerrun/nativescript-ngx-magic';
#Component({
moduleId: module.id,
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css']
})
export class AppComponent {
title = 'app works!';
}
now run the app
> npm run start.android
The app works
Then I create a custom control:
> ng g component custom
then again Create a blank custom.component.tns.css
create a new custom.component.tns.html
<Label text="My Custom Component" class="h1 text-center"></Label>
Change the custom.component.ts code:
import { Component } from '#wwwalkerrun/nativescript-ngx-magic';
#Component({
moduleId: module.id,
selector: 'app-custom',
templateUrl: 'custom.component.html',
styleUrls: ['custom.component.css']
})
export class CustomComponent {
}
and add this custom tag into my app.component.tns.html so now it looks like this:
<ActionBar title="Magic!" icon="" class="action-bar">
</ActionBar>
<StackLayout class="p-20">
<Label text="NativeScript is Neat." class="h1 text-center"></Label>
<app-custom></app-custom>
</StackLayout>
Then when I run the app again:
> npm run start.android
I expect to see my custom component, but the app just looks the same.
What am I missing?
If I add a custom component into the .html file, not the tns.html and run using ng serve, then the website shows the custom component correctly. Just not the app.
Is this even possible when using the nativescript-ngx-magic?
I found the reason.
The nativescript-ngx-magic command creates a nativescript directory, in here there is an app folder and in here another app folder. This inner app folder is a symbolic link to the app folder in the main src folder. But in the outer app folder there is a second app.module.ts file which is generated. This is where the NativeScriptModule is imported. When I created the custom control: > ng g component custom then this component was automatically registered in the app.module.ts within the inner app folder (shared on the symbolic link). But it was not registered in the app.module.ts which is for nativescript. This explains why the custom component was visible for the website but not for the app. I needed to register the custom component in this second app.module.ts in the declarations section, so this app.module.ts now looks like:
import { NgModule, NO_ERRORS_SCHEMA } from '#angular/core';
import { NativeScriptModule } from 'nativescript-angular/nativescript.module';
import { AppComponent } from './app/app.component';
import { CustomComponent } from "./app/custom/custom.component";
#NgModule({
bootstrap: [
AppComponent
],
imports: [
NativeScriptModule
],
declarations: [
AppComponent, CustomComponent
],
schemas: [
NO_ERRORS_SCHEMA
]
})
export class AppModule { }
Once I did this, then the custom component was shown in the app too.

Angular2 access to the methods in child component from parent

My question is about the way of have access to childerns component methods from parent component. I found solution which is describe using below example, but I afraid that may be I do it in wrong, not 'angular2 right' way.
For instance we have child:
#Component({ ... })
export class Modal {
...
open() {
...
}
}
And parent:
import { Modal } from '../common';
...
#Component({
selector: 'editor',
directives: [ Modal ],
templateUrl: './editor.html',
...
})
export class Editor {
_modal = null;
...
bindModal(modal) { this._modal=modal; }
open() {
this._modal.open();
}
}
And in editor.html:
<button (click)="open()">Open Editor</button>
<modal #editModal>{{ bindModal(editModal) }}
Here is my editor body in modal (popup) window
...
</modal>
This is solution for have access from Editor component to the open() method inside Modal component. It is a little bit tricky. The question is: is there a simplest and more direct way without using 'bindModal' method?
There are many ways to do it,
#ViewChild
import {ViewChild} from '#angular/core';
import { Modal } from '../common';
...
#Component({
selector: 'editor',
directives: [ Modal ],
templateUrl: './editor.html',
...
})
export class Editor {
#ViewChild(Modal) md:Modal;
Open()
{
this.md.open();
}
}
Other way is to use #localVariable and from parent itself you can access child methods.

Resources