call ngOnDestroy programmatically on design time component in angular 5 - angular5

I am showing an custom component("my-addmodule") inside the modal Dialog custom component( "my-modal-dialog") as below,
<my-modal-dialog [showFooter]="false" #addModuleDialog>
<my-addmodule (hideDialog)="hideAddModalDialog($event)" (reloadGrid)="reload($event)" #addModule></my-addmodule>
</div>
</my-modal-dialog>
Now the problem is that, each time, I close the modal dialog, angular is not destroying "my-addmodule" component. So when I open the modal-dialog again, I see the same state of "my-addmodule" component ( some drop-down selection and previously entered value in textbox etc).
I want angular to destroy component when I close the modal-dialog and re-create the component on opening the modal-dialog.
I tried adding the below code ""my-addmodule" component,
export class AddModuleComponent implements OnInit, OnDestroy {
public destroyComponent(){
this.ngOnDestroy();
}
ngOnDestroy(): void {
console.log("Add module is destroyed");
}
}
but when I call "destroyComponent" function on the modal-dialog hide() function, I get error "this.addModuleDialog.destroyComponent is not a function".
following is my parent component ts file, who is using above mentioned two component,
ParentComponent.ts
export class ParentComponent implements {
#ViewChild('addModuleDialog') addModuleDialog;
#ViewChild('addModule') addModule;
showAddModuleDialog(e: any): void {
e.preventDefault();
this.addModuleDialog.show();
}
hideAddModalDialog(e: any): void {
this.addModuleDialog.hide();
this.addModule.destroyComponent();
}
}
Parent.Component.html
<my-modal-dialog [showFooter]="false" #addModuleDialog>
<my-addmodule (hideDialog)="hideAddModalDialog($event)" (reloadGrid)="reload($event)" #addModule></my-addmodule>
</div>
</my-modal-dialog>

Related

Vue.js 3 : Accessing a dynamically created component

I have a vue.js 3 application that needs to dynamically create components and access them.
The proper way to dynamically create them and injected them in the DOM seems to be th wrap them in an app using createApp, and this part works, when I call test() a new copy of the components appears at the bottom of the DOM.
Now I need to be able to get a reference to that component son I can call public (exposed) methods on it.
In my (actual) code below, what would allow me to get a reference to my component ?
import { createApp, h } from "vue";
import ConfirmModal from '#/views/components/ui/confirm-modal.vue';
function test()
{
let componentApp = createApp({
setup() {
return () => h(ConfirmModal, { title: "Fuck yeah!", type: "primary" });
}
});
const wrapper = document.createElement('div');
wrapper.setAttribute('id', 'confirm-modal-0');
componentApp.mount(wrapper);
document.body.appendChild(wrapper);
let _confirmModal: ConfirmModal = ???????????????????
_confirmModal.show();
}
EDIT : Here's my use-case: I have a helper function in a service which is used to confirm actions (like deletes) using a Modal dialog. This helper/service is pure TS, not a Vue component, but needs to instanciate the modal (which is a vue component), have it injected in the DOM and have its public methods callable (by my helper/service).
Right now, the only thing that works is to have a sungle copy of the modal component in my root layout and have to root layout foward the ref to my service, which can then use the component. But this isn't great because I need multiple instances of the dialog, and isn't good SOC to have to root layout handle a modal dialog.

Add custom CSS class to element `.ck-content` in CKEdtior5 and Vue2

How to add custom CSS class to element .ck-content, by other words, to editable formatted text container in CKEditor5 and Vue2?
The ck-content is the input field; we must differ it from the toolbar above, the other part of CKEditor. So if we want to apply some class affecting only to inputted content, it must not affect to toolbar.
Seems to be obvious solution:
<ckeditor class="CustomClass" :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
will not work because CustomClass it will not be applied to .ck-content and even not to root element.
Below solution will not work too, because when CKEditorWrapper mounted, the CKEditor mounting has not complete yet.
import CK_EditorVueAdaptation from "#ckeditor/ckeditor5-vue2";
#Component({
components: {
ckeditor: (CK_EditorVueAdaptation as { component: VueClass<unknown>; }).component
}
})
class CKEditorWrapper extends Vue {
private mounted(): void {
this.$el.getElementsByClassName("ck-content").item(0) // null
}
}
Vue CKeditor component emits ready event when it's really mounted and rendered. So an easy solution: catch it and add the class to the wanted node, having in mind that this.$el is the sibling of the real container of the editor.
<ckeditor
...
#ready="onEditorReady"
/>
...
,
methods: {
onEditorReady () {
const myClass = 'anyCustomClass'
const addCustomClass = () => this.$el.nextSibling
.querySelector('.ck-content')
.classList
.add(myClass)
this.$nextTick(addCustomClass)
}
}

Failed to access innerhtml elements in angular5

I am trying to access innerhtml elements in my component using it's id attribute.It works if I add the element directly into my template,but when I added the element through html binding I failed to access it in component.
html
<div [innerHtml]="testVal | safingHtml"></div>
component
testVal='<a id="up1">hello</a>';
ngAfterViewInit() {
const elem=document.querySelector('#up1');
console.log(elem);
}
In the above code I am trying to access the html elelment after completing the initialization process.The code works if I added the elelment directly into the template otherwise it returns null.
I am also using custom pipe having 'DomSanitizer' to get the html attributes(id,style).
custom pipe
import {DomSanitizer} from '#angular/platform-browser';
import {PipeTransform, Pipe} from "#angular/core";
#Pipe({ name: 'safingHtml'})
export class SafingHtmlPipe implements PipeTransform {
constructor(private sanitized: DomSanitizer) {}
transform(value) {
return this.sanitized.bypassSecurityTrustHtml(value);
}
}
is there anyway to access the innerhtml elements by using it's id apart from using 'viewchild' property in angular5?

Aurelia - call function on nested component

I want to call a child component's function from its parent. I have a way to do it, but I want to know if I'm missing a better way.
From Ashley Grant's blog post about accessing a custom element's viewModel from a custom attribute, I see that Aurelia adds au to the element and you can access the viewModel through that. So, if I add a nested component with a ref, like this:
<template>
<nested-element ref="childElement"></nested-element>
</template>
I can call a function on it like this:
this.childElement.au.controller.viewModel.someFunction();
This feels roundabout. I was hoping I would be able to access a nested element's viewModel through the parameters to a hook that the parent implements, such as created(owningView, myView) but I can't find a path to it.
Have I missed a better way?
Edit: I forgot to add that I need a return value from the function I'm calling, so having access to the viewmodel itself is preferable
ref gives you the element. view-model.ref gives you the element's view model.
<template>
<nested-element view-model.ref="childViewModel"></nested-element>
</template>
Call it like this in the parent view-model:
this.childViewModel.someFunction();
If you only have one instance of the nested-element or don't care if multiple nested-elements respond to the event. Then you could use standard Javascript event functionality for this:
bar.html
<template>
<h1>${value}</h1>
<input type="text" value.bind="value"></input>
<foo>text</foo>
</template>
bar.ts
import {bindable} from 'aurelia-framework';
export class Bar {
#bindable value;
public valueChanged(newValue, oldValue) {
var event = new CustomEvent("some-event-name", { "detail": { message: "Hello from Bar", oldValue, newValue } });
document.dispatchEvent(event);
}
}
foo.html
<template>
<h1>${value}</h1>
</template>
foo.ts
import {bindable} from 'aurelia-framework';
export class Foo {
constructor() {
document.addEventListener("some-event-name", (e) => {
console.log('hello here is Foo, recieved event from Bar : ', e);
}, true);
}
}

how to open authentification popup or modal in Angular 2

I am trying to code a login component for my application in Angular 2 version rc-1. But I did not find how to open my modal without a button action.
When I load my app, I check if the user is logged or not (with the localStorage) : if he is not logged the login modal had to be openned.
So open/close modal is conditionned by a boolean parameter and not a action button.
Do you know how can I open a login modal without a button action ?
Thanks in advance,
Lets say you have a component that holds your modal.
export class YourModalComponent {
constructor () {}
public open(): void {
//show modal
}
}
And then you have a component that checks the local storage and has YourModalComponent as a children. If the user is logged in you just call modal.open().
export class YourParentComponent {
#ViewChild(YourModalComponent)
public yourModal : YourModalComponent;
constructor() {}
public ngAfterViewInit(): void {
//check if user is logged in
if(!userIsLoggedIn) {
this.yourModal.open();
}
}
}
You can also have the div displaying with ngIf so the YourModalComponent is only displayed if it meets the condition.