javascripthtmlangularjstypescriptng-bind-html

TypeScript + AngularJS : Can't interact with the html generated by ng-bind-html


I have an html string that i build dynamically in my Component's controller. This way :

    let strDl = this.domainsLabel.split('>');
            angular.forEach(strDl, (element, index) => {
                if (index < strDl.length - 1)
                    this.domainsLabelHtml += `<a position="${index}" ng-click="TabsDomains.goTo($event.target)">${element}</a>&#62;`;
                else
                    this.domainsLabelHtml += `${element}`;
            });
            if (this.domainsLabelHtml.endsWith('&#62;'))
                this.domainsLabelHtml = this.domainsLabelHtml.slice(0, -5);

The html code :

    <span ng-bind-html="TabsDomains.trustedHtml(TabsDomains.domainsLabelHtml)"></span>

I get the following result :

dynamicallyGeneratedCode

But nothing happens when I click. Since nothing worked, i wrote an html content manually, like this :

    <span><a position="0" ng-click="TabsDomains.goTo($event.target)">TEST</a>blabla</span>

And i get the following result generated staticCode:

Which works perfectly.

Since the two chunks of code look exactly the same to me, I don't understand why the dynamically generated isn't working and the static one does.

Here is the code of the trusted html :

     public trustedHtml = function (plainText) {
        return this.$sce.trustAsHtml(plainText);
    }

My class looks like this :

    /// <reference path='tabs.d.ts'/>

    module rundeckManager.tabs {
        'use strict';

class TabsDomainsComponentController implements ITabsDomainsComponentController {

    static $inject = ['$filter', '$state','$rootScope','jobService','$sce','$compile','$scope'];
    public test = false;
    public domainsLabel: any;
    public jobsLabel: any;
    public domains: any;
    public jobs: any;  
    //Previous domains and jobs of the hierarchy
    //So we always keep the data, no need to reprocess it
    public pDomains: any;
    public ppDomains: any;
    public pppDomains: any;
    public pJobs: any;
    public ppJobs: any;
    public pppJobs: any;
    public pFolder: any;
    public ppFolder: any;
    public pppFolder: any;

    public firstBack: any;
    public jobDetails: jobs.IJobDetails;
    public idJob: string;
    public showJobDetails: boolean;
    public showLoadingBar: boolean;
    public domainsLabelHtml: any;

    constructor(public $filter: any, public $state: any, public $rootScope: any, public jobService: jobs.IJobService, public $sce: any, public $compile: any, public $scope: ng.IScope) {
        this.firstBack = $rootScope.back;
        this.showJobDetails = false;
        this.showLoadingBar = false;
        this.domainsLabelHtml = ``;
    }

    public $onChanges(changes) {
        if (changes.domains) {
            this.domains = changes.domains.currentValue;
        }
        if (changes.jobs) {
            this.jobs = changes.jobs.currentValue;
        }
        if (changes.domainsLabel) {
            this.domainsLabel = changes.domainsLabel.currentValue;
            let strDl = this.domainsLabel.split('>');
            angular.forEach(strDl, (element, index) => {
                if (index < strDl.length - 1)
                    this.domainsLabelHtml += `<a position="${index}" ng-click="TabsDomains.goTo($event.target)">${element}</a>&#62;`;
                else
                    this.domainsLabelHtml += `${element}`;
            });
            if (this.domainsLabelHtml.endsWith('&#62;'))
                this.domainsLabelHtml = this.domainsLabelHtml.slice(0, -5);




            this.$compile(document.querySelector('#id-of-span'))(this.$scope);                
        }
        if (changes.jobsLabel) {
            this.jobsLabel = changes.jobsLabel.currentValue;
        }
    }

    public trustedHtml(plainText: string) {
        return this.$sce.trustAsHtml(plainText);
    }

    public goToDetails(id: string) {
        this.idJob = id;
        //console.log(id);
        this.showLoadingBar = true;
        this.jobService.getJobDetails(id).then((data) => {
            this.jobDetails = data.data.job;               
            this.showJobDetails = true;
            this.showLoadingBar = false;
        });              

        this.$rootScope.back = () => {
            this.showJobDetails = false;
            this.showLoadingBar = false;
            this.$rootScope.back = this.firstBack;
        };
    }

    public goTo(element:any) {
        let position = element.attributes['position'].value;
        let strDomains = this.domainsLabel.split('>');            
        console.log('its working');
    }

    public redirectTo(name: string) {
        switch (this.$state.current.name) {
            case 'root.domains':
                var proj = this.$filter('filter')(this.domains, { id: name }, true);
                var subDomainsParam = proj[0].subDomains;
                var jobsParam = proj[0].jobs;
                var obj = {
                    subDomName: this.domainsLabel + '>' + name,
                    pDomains: this.domains,
                    subDomains: subDomainsParam,
                    jobs: jobsParam,
                    pJobs: this.jobs,
                    pFolder: this.domainsLabel
                };
                this.$state.go('root.subDomains', obj);
                break;
            case 'root.subDomains':
                var proj = this.$filter('filter')(this.domains, { id: name }, true);
                var subSubDomainsParam = proj[0].subSubDomains;
                var jobsParam = proj[0].jobs;
                var obj2 = {
                    subSubDomName: this.domainsLabel + '>' + name,
                    pDomains: this.domains,
                    ppDomains: this.pDomains,
                    subSubDomains: subSubDomainsParam,
                    jobs: jobsParam,
                    pJobs: this.jobs,
                    ppJobs: this.pJobs,
                    pFolder: this.domainsLabel,
                    ppFolder: this.pFolder
                };

                this.$state.go('root.subSubDomains', obj2);
                break;
            case 'root.subSubDomains':
                var proj = this.$filter('filter')(this.domains, { id: name }, true);
                var jobsParam = proj[0].jobs;
                var obj1 = {
                    lastLevelName: this.domainsLabel + '>' + name,
                    pDomains: this.domains,
                    ppDomains: this.pDomains,
                    pppDomains: this.ppDomains,
                    jobs: jobsParam,
                    pJobs: this.jobs,
                    ppJobs: this.pJobs,
                    pFolder: this.domainsLabel,
                    ppFolder: this.pFolder,
                    pppFolder: this.ppFolder
                };

                this.$state.go('root.lastLevel', obj1);
                break;
        }
    }
}

class TabsDomainsComponent implements ng.IComponentOptions {
    public bindings: any;
    public controller: any;
    public controllerAs: string;
    public templateUrl: string;

    constructor() {
        this.bindings = {
            domains: '<',
            jobs: '<',
            jobsLabel: '<',
            domainsLabel: '<',
            pDomains: '<',
            ppDomains: '<',
            pppDomains: '<',
            pJobs: '<',
            ppJobs: '<',
            pppJobs: '<',
            pFolder: '<',
            ppFolder: '<',
            pppFolder: '<'
        };
        this.controller = TabsDomainsComponentController;
        this.controllerAs = 'TabsDomains';
        this.templateUrl = 'public/app/views/components/tabsDomains/tabs.domains.html';
    }

}

angular.module('rundeckManager.tabs')
    .component('tabsDomains', new TabsDomainsComponent());

    }

I found an answer which looked like the problem I'm having at first, but the solution didn't apply to my case :

Links not working in ng-bind-html

I'd be great if anyone can explain it to me and help me with a solution.

Thank you


Solution

  • You have to run $compile(this.domainsLabelHtml)($scope); after you inject Html code, that should be managed by Angular.

    EDIT

    I think compiling this.domainsLabelHtml might not work. Try to add an Id to than span that should bind the Html and than do:

    //Html
     <span id="id-of-span" ng-bind-html="TabsDomains.trustedHtml(TabsDomains.domainsLabelHtml)"></span>
    
    //JS
    $compile(angular.element('#id-of-span'))($scope);