Capacitor v3 Motion api - using AccelListenerEvent properties - ionic-framework

I am using Capacitor version 3 and I'm trying out the Motion Api.
In the documentation here, the AccelListenerEvent comes with some properties which I want to set but there are no examples of how to use this.
So the part I'm using is addListener(‘orientation’, …)
I basically want to set the interval.
I've added this:
import { Component } from '#angular/core';
import { PluginListenerHandle } from '#capacitor/core';
import { Motion, AccelListenerEvent } from '#capacitor/motion';
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
accelHandler: PluginListenerHandle;
accelListenerEvent: AccelListenerEvent;
constructor() {
this.accelListenerEvent.interval = 10;
}
But it doesn't like it in the constructor.
Does anyone have any ideas on how to set these properties?

You can access the properties this way:
Motion.addListener('accel', event => {
console.log('Interval:', event.interval);
});
Since this is an event, you can only receive values, not set them.

Related

How to hide header on scroll in ionic 4?

I wanted to know how I can hide a header in Ionic 4 by scrolling down the page, and re-show it when scrolling up.
I found many solutions on how to do that, but they all turned out to not working or being out-of-date.
So I collected all piece of information I could find to provide this answer.
Thanks to this video I got it to work.
First of all call ionic g directive directives/hide-header. You can of course replace directive/hide-header with your own path and name.
hide-header.directive.ts
import { Directive, HostListener, Input, OnInit, Renderer2 } from '#angular/core';
import { DomController } from '#ionic/angular';
#Directive({
selector: '[appHideHeader]'
})
export class HideHeaderDirective implements OnInit {
#Input('header') header: any;
private lastY = 0;
constructor(
private renderer: Renderer2,
private domCtrl: DomController
) { }
ngOnInit(): void {
this.header = this.header.el;
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'transition', 'margin-top 700ms');
});
}
#HostListener('ionScroll', ['$event']) onContentScroll($event: any) {
if ($event.detail.scrollTop > this.lastY) {
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'margin-top', `-${ this.header.clientHeight }px`);
});
} else {
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'margin-top', '0');
});
}
this.lastY = $event.detail.scrollTop;
}
}
After that, in your template:
<ion-header #header>
<ion-toolbar><ion-title>Test</ion-title></ion-toolbar>
</ion-header>
<ion-content scrollEvents="true" appHideHeader [header]="header">
</ion-content>
Take care of the scrollEvents, appHideHeader and the [header] attributes! The last one takes the header element as argument, in this case #header.
Most of the code is the same as shown in the video. I changed the host-property from the #Directive and used the more up-to-date HostListener.
If you want to use the directive in more than one directive, you need to create a SharedModule.
To do so, create the module with ng g module shared. After that, add the HideHeaderDirective to the declarations and the exports array.
shared.module.ts
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { HideHeaderDirective } from './directives/hide-header.directive';
#NgModule({
declarations: [HideHeaderDirective],
exports: [HideHeaderDirective],
imports: [
CommonModule
]
})
export class SharedModule {}
Now add the shared module to all the modules you want to use the directive in.
Note: You cannot import the directive in app.module.ts and use it in a submodule! You have to import the shared module in every direct module you want to use the directive in.
My current versions of node, npm and ionic:
For this you can just place the ion-header before the ion-content. this is the simple answer for that.

How to see the state of the battery with Ionic4?

I can not get the battery data, the level of charge and whether it is connected or not, what am I doing wrong? Thank you in advance.
I'm placing "BatteryStatus" in app.module.ts in providers. The code of the home is only for printing on the console while there is a change in the battery. I am using the example of the Ionic 4 documentation but still I have the following error: ERROR TypeError: Invalid event target.
I HAVE FOLLOWED THE SENTENCES OF THE DOCUMENTATION
The code of the home is the following:
import { Component } from '#angular/core';
import { BatteryStatus } from '#ionic-native/battery-status/ngx';
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
subscription: any;
constructor(private batteryStatus: BatteryStatus) {
this.checkStatus()
}
checkStatus(){
this.subscription = this.batteryStatus.onChange().subscribe(status => {
console.log(status.level, status.isPlugged);
});
}
stop(){
// stop watch
this.subscription.unsubscribe();
}
}
I hope that the status value of the battery is printed in the console, but I get the following error:
Error

How to get DOM nodes class list using Renderer2

Since Angular 4.0.0, Renderer2 should be used to access DOM nodes. I can’t find a way to access the class List of a DOM node. I can easily add or remove a class but I can’t get a class List. Am I missing something?
import { Component, ElementRef, Renderer2 } from '#angular/core';
#Component({
selector: 'auto-form',
template: `<form formContainer class="test"></form>
`
})
export class AutoFormComponent {
constructor(private formContainer:Renderer2) {
}
}
Renderer2 Documentation
There is no way to get any information from the DOM using Renderer. The renderer is only one-way - from code to DOM.
https://angular.io/docs/ts/latest/api/core/index/Renderer2-class.html
Ok, it seems there are 3 exceptions:
selectRootElement
parentNode
nextSibling

Angular2: Get dimensions of DOM-Element (without ElementRef)

I try to get dimensions of a DOM-Element (heigtht/width).
As for security reasons (see https://angular.io/docs/ts/latest/guide/security.html) I don't want to directly acccess the DOM.
Does anyone have some other Idea?
You could do it like this
import { Component } from '#angular/core';
#Component({
selector: 'my-selector',
template: '<div #myDiv (click)=getElementDimensions(myDiv)>Hello</div>'
})
export class AboutComponent {
constructor() { }
getElementDimensions(el: HTMLDivElement) {
console.log(el.getBoundingClientRect())
}
}
As I thought more about my Question:
Actually accessing the DOM-Element through ElementRef is no security threat in this case, as no (unsafe-)data is injected through it.
If you want to get around using ElementRef (eg. for server side rendering) and want to manipulate a DOM-Element I recommend to look at the Renderer class.

Angular2 Undefined Object attribute when using a callback function as Component #Input()

Im trying to bind a callback function to a directive, when the event is fired the attribute of the parent component are undefined
app.ts
import {Component} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {MyComponent} from './my-component';
#Component({
selector: 'my-app',
template: `
<button (click)="appOnClick('CLICK FROM APP')">BUTTOM OUTSIDE COMPONENT</button>
<br><br>
<my-component [onClick]="appOnClick"></my-component>`,
directives: [MyComponent]
})
export class MyApp {
public theBoundCallback: Function;
test:string = "THIS SHOULD HAVE A VALUE";
public ngOnInit(){
this.theBoundCallback = this.appOnClick.bind(this);
}
appOnClick(someText){
console.log(someText);
console.log(this.test);
}
}
bootstrap(MyApp);
my-component.ts
import {Component, Input} from 'angular2/core';
#Component({
selector: 'my-component',
template: `<button (click)="onClick('CLICK FROM COMPONENT')">BUTTOM INSIDE COMPONENT</button>`
})
export class MyComponent{
#Input() onClick: Function;
}
That will render two buttons:
BUTTOM OUTSIDE COMPONENT, this calls the appOnClick function direct from the app, when clicked the console shows:
- CLICK FROM APP
- THIS SHOULD HAVE A VALUE
BUTTOM INSIDE COMPONENT, this calls the appOnClick function via the #Input function in the component, when clicked the console shows:
- CLICK FROM APP
- undefined
I've created the example on Plunker
Is that a way to assign this correctly so I can work with my object attributes when the callback is trigger?
Updated plunkr
In order to pass appOnClick around this way, you need to declare it as a property like so:
export class MyApp {
...
appOnClick = (someText) => {
console.log(someText);
console.log(this.test);
}
}
instead of:
export class MyApp {
...
appOnClick(someText){
console.log(someText);
console.log(this.test);
}
}
I think that you forgot "(...)" when using the appOnClick method and use "[...]" instead of "(...)" when configuring the event handler:
<my-component (onClick)="appOnClick($event)"></my-component>`,
Moreover within your sub component you need to define a custom event with "#Output":
#Component({
selector: 'my-component',
template: `<button (click)="handleClick('CLICK FROM COMPONENT')">BUTTOM INSIDE COMPONENT</button>`
})
export class MyComponent{
#Output()
onClick:EventEmitter<string> = new EventEmitter();
handleClick(txt:string) {
this.onClick.emit(txt);
}
}