How to create directive for disable input in reactive form with Angular 8^? - angular8

The old directive from angular 6 doesn't working more.
(I need directive and not sample code in the component because of the need for dynamism that changes during the run.
this is the old directive code:
import { Directive, Input } from "#angular/core";
import { NgControl } from "#angular/forms";
#Directive({
selector: "([formControlName], [formControl])[disabledControl]"
})
export class DisabledControlDirective {
#Input() set disabledControl(state: boolean) {
const action = state ? "disable" : "enable";
this.ngControl.control[action]();
}
constructor(private readonly ngControl: NgControl) {}
}

Related

How can I access ngOffline directive in a component instead of html

I'm using this npm library https://www.npmjs.com/package/ng-offline to alert end user when offline.
<div class="alert alert-danger" ngOffline>You're offline. Check your connection!</div>
stackblitz here: https://stackblitz.com/edit/angular-ngoffline-npm?file=src%2Fapp%2Fapp.component.html
Works great - BUT I want to open a modal with this ngOffline directive, so I'm trying to access the directive from my angular 11 component but not sure how to approach this, any help on this would be greatly appreciated.
Is there away for me to open a ngx-bootstrap modal from the html with this directive?
Because the ng-offline module isn't exporting things as you might expect (i.e. you can't inject a standalone NgOfflineDirective for you to use without having it in your html file), you could add a block like this (where you've used #trigger to identify your ngOnline element):
import { AfterContentChecked, Component, ElementRef, OnDestroy, ViewChild } from '#angular/core';
import { BehaviorSubject, Subscription } from 'rxjs';
import { distinctUntilChanged, filter } from 'rxjs/operators';
#Component({ ... })
export class YourClass implements AfterContentChecked, OnDestroy {
offline$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>();
subscription: Subscription;
#ViewChild('trigger') trigger: ElementRef;
constructor() {
this.subscription = this.offline$.pipe(
distinctUntilChanged(),
filter((offline: boolean) => offline),
).subscribe(() => this.showModal());
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
ngAfterContentChecked() {
if (
this.trigger &&
this.trigger.nativeElement
) {
this.offline$.next(this.trigger.nativeElement.style.display === "none");
}
}
showModal() {
console.log('Show your modal here.');
}
}

How to use my own class inside a Vue file

I'm making a webpage using Nuxt and I would like to make a class and use it in one of my .vue files. I've tried using an import: import Card from "~/assets/mylib/Card.js" but that doesn't work. Not sure how to access my Card.js file inside of a .vue file.
index.vue
import Card from "~/assets/mylib/Card.js"
created() {
let card = new Card("blue")
}
Card.js
class Card {
constructor(color) {
this.color = color
}
}
error:
_assets_mylib_Card_js__WEBPACK_IMPORTED_MODULE_4___default.a is not a constructor
Modify Card.js as follows:
export default class Card {
constructor(color) {
this.color = color
}
}
Then import it from within index.vue as follows:
import { Card } from "~/assets/mylib/Card"
you have to update your Card.js like beow
export class Card {
constructor(color) {
this.color = color
}
}
and import in vue file like below
import { Card } from "~/assets/mylib/Card"

How to susbscribe to property on the state in Vue?

I have vue application.
I'm using vuex and vuex-class packages to connect with the store.
in my component(vue-property-decorator) I want to subscribe to some property on the state, and when it change then I want to know.
for example:
my state for example:
const state = {
error: null,
};
and getters:
const getters = {
error(state: any) {
return state.error;
},
};
my component:
import { Component } from 'vue-property-decorator';
import { namespace } from 'vuex-class';
const SomeModule = namespace('somemodule');
#Component({})
export default class MyPage extends SomeBaseComponent {
#SomeModule.Getter('error')
error: any;
// HOW TO know when error has change?
}
onErrorChanged() {
//?????
}
I want onErrorChanged will fire every time the error property on the state changed.
How to do that?
I'm a maintainer of vue-property-docorator. Thanks for using the library.
If you'd like to observe the changes of error property, you can do it by $watch.
As you are using vue-property-decorator, #Watch decorator is available.
#Component({})
export default class MyPage extends SomeBaseComponent {
#SomeModule.Getter('error')
error: any;
#Watch('error')
onErrorChanged(newErrorVal, oldErrorVal) { }
}

Inheritance of Angular 5 components with overriding the decorator properties

In Angular 2/4 we could create custom decorator for extending parent component. Actual overriding of the decorator properties was handled as needed in the custom decorator. To get parent annotations we used:
let parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
After update to Angular 5 this doesn't work anymore. Regarding this
answer we could use:
target['__annotations__'][0] for getting parent component annotations.
In order to set annotations in the current component in Angular 2/4 we used:
let metadata = new Component(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
How can set current component annotations in Angular 5?
At the end I came up to this implementation of a custom decorator (extendedcomponent.decorator.ts):
import { Component } from '#angular/core';
export function ExtendedComponent(extendedConfig: Component = {}) {
return function (target: Function) {
const ANNOTATIONS = '__annotations__';
const PARAMETERS = '__paramaters__';
const PROP_METADATA = '__prop__metadata__';
const annotations = target[ANNOTATIONS] || [];
const parameters = target[PARAMETERS] || [];
const propMetadata = target[PROP_METADATA] || [];
if (annotations.length > 0) {
const parentAnnotations = Object.assign({}, annotations[0]);
Object.keys(parentAnnotations).forEach(key => {
if (parentAnnotations.hasOwnProperty(key)) {
if (!extendedConfig.hasOwnProperty(key)) {
extendedConfig[key] = parentAnnotations[key];
annotations[0][key] = '';
} else {
if (extendedConfig[key] === parentAnnotations[key]){
annotations[0][key] = '';
}
}
}
});
}
return Component(extendedConfig)(target);
};
}
Example usage:
First implement the parent component as usual (myparent.component.ts):
import { Component, Output, EventEmitter, Input } from '#angular/core';
#Component({
selector: 'my-component',
templateUrl: 'my.component.html'
})
export class MyParentComponent implements OnInit {
#Input() someInput: Array<any>;
#Output() onChange: EventEmitter<any> = new EventEmitter();
constructor(
public formatting: FormattingService
) {
}
ngOnInit() {
}
onClick() {
this.onChange.emit();
}
}
After that implement child component which inherit the parent component:
import { Component, OnInit } from '#angular/core';
import { ExtendedComponent } from './extendedcomponent.decorator';
import { MyParentComponent } from './myparent.component';
#ExtendedComponent ({
templateUrl: 'mychild.component.html'
})
export class MyChildComponent extends MyParentComponent {
}
Note: This is not officially documented and may not work in many cases. I hope that it will help somebody else, but use it at your own risk.

Angular 2 Directive and FormGroup: to change all input text to uppercase

Please help. I'm having trouble creating a generic directive that will always set all the inputs type text to uppercase.
below is my directive:
import { Directive, ElementRef, HostListener } from '#angular/core';
import { NgControl } from "#angular/forms";
#Directive({
selector: 'input[type="text"]:not(.none-transform)',
host:{
'(input)':'format($event)'
}
})
export class TextUppercase {
constructor(private _el: ElementRef, private _control? : NgControl) {
}
format(value) {
let uppercase = this._el.nativeElement.value.toUpperCase();
this._control.control.setValue(uppercase);
}
}
When I didn't set the formControl in my form, this error come:
ERROR Error: Uncaught (in promise): Error: No provider for NgControl!
Error: No provider for NgControl!
How to make the directive still working even the formControl is not set?