0

I want to dynamically disable click events from a certain DOM. I figured a directive should do the trick. Apparently it is not possible to add / remove directives dynamically, so I just added the conditional parameter:

import { Directive, HostListener, Input } from '@angular/core';

    @Directive({
        selector: '[disableClickEvent]',
    })
    export class DisableClickEventDirective {
        @HostListener('click', ['$event'])
        // workaround as directives can not (yet) be added dynamically
        @Input()

        disableClickEvent: boolean;

        public onClick(event: any): void {
            if (this.disableClickEvent) {
                event.stopPropagation();
            }
        }
    }

and my html:

<div class="modal-body">
    <ng-container class="content" *ngIf="exportTypeSelectionModel$ | async; let exportTypeSelectionModel">
        <ul>
            <li              
                [disableClickEvent]="!exportTypeSelectionModel.Condition"
                [class.disabled]="!exportTypeSelectionModel.Condition"
            >                   
                <span>Some list item</span>
            </li>          
        </ul>
    </ng-container>
</div>

I always end up with this when clicking on the li

ng:///SharedModule/MyComponent.ngfactory.js:10 ERROR TypeError: jit_nodeValue_3(...).disableClickEvent is not a function
    at Object.eval [as handleEvent] (ng:///SharedModule/MyComponent.ngfactory.js:15)
    at handleEvent (:4200/vendor.js:98419)
    at callWithDebugContext (:4200/vendor.js:100038)
    at Object.debugHandleEvent [as handleEvent] (:4200/vendor.js:99673)
    at dispatchEvent (:4200/vendor.js:85506)
    at :4200/vendor.js:97351
    at HTMLLIElement.<anonymous> (:4200/vendor.js:117167)
    at ZoneDelegate.invokeTask (:4200/polyfills.js:3722)
    at Object.onInvokeTask (:4200/vendor.js:94422)
2
  • can you make a stackblitz Commented Feb 11, 2020 at 10:08
  • I don't see the directive selector eveDisableClickEvent mentioned in your li tag. Also wouldn't hurt to declare @Input decorator above @HostListener decorator. Commented Feb 11, 2020 at 10:25

1 Answer 1

1

First you need to attach your directive to li. Like:

<li eveDisableClickEvent [disableClickEvent]="!exportTypeSelectionModel.Condition" ... >. Then in the directive file you should move your function under the host listener decorator. Like: this

    @HostListener('click', ['$event'])
    onClick(event: any): void {
            if (this.disableClickEvent) {
                event.stopPropagation();
            }
        }

That should help. But it would be better to have some stackblitz with use-case. P.s the thing is that @HostListener needs handler function but in your case compiler goes down and encounter first "disableClickEvent" property which is boolean, so it throws the error that "disableClickEvent is not a function"

Sign up to request clarification or add additional context in comments.

5 Comments

Okay this might work but Angular documentation explicitely says, that passing parameters can be simplified: '<p appHighlight [highlightColor]="color">Highlighted with parent component's color</p> That's good, but it would be nice to simultaneously apply the directive and set the color in the same attribute like this.' And so they end up with this syntax: '<p [appHighlight]="color">Highlight me!</p>' which is excactly what I am trying to do.
Ah I now I undestand: as you and Micheal pointed out, this is because of malformed directive member declaration. I have to move Input above @Hostlistener
@yBother yes, that's true, but to achieve this you have to have the same @Input name and selector name. So you have to rename @Input() disableClickEvent to @Input() eveDisableClickEvent and then you could use it like <li [eveDisableClickEvent]="true">`. But this is another issue. The error points out on the case I described in answer :)
dont bother with 'eveDisableClickEvent' this is just a typo. I made sure that directive selector and name of input do match.
@yBother ah ok. Now I see.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.