TypeScript + AngularJS :无法与 ng-bind-html 生成的 html 交互
TypeScript + AngularJS : Can't interact with the html generated by ng-bind-html
我有一个 html 字符串,它是我在组件的控制器中动态构建的。这样:
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>>`;
else
this.domainsLabelHtml += `${element}`;
});
if (this.domainsLabelHtml.endsWith('>'))
this.domainsLabelHtml = this.domainsLabelHtml.slice(0, -5);
html代码:
<span ng-bind-html="TabsDomains.trustedHtml(TabsDomains.domainsLabelHtml)"></span>
我得到以下结果:
dynamicallyGeneratedCode
但是当我点击时没有任何反应。
由于没有任何效果,我手动写了一个 html 内容,如下所示:
<span><a position="0" ng-click="TabsDomains.goTo($event.target)">TEST</a>blabla</span>
我生成了以下结果 staticCode:
效果很好。
由于这两段代码在我看来完全一样,所以我不明白为什么动态生成的代码不起作用而静态代码却起作用。
这是受信任的 html 的代码:
public trustedHtml = function (plainText) {
return this.$sce.trustAsHtml(plainText);
}
我的 class 看起来像这样:
/// <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>>`;
else
this.domainsLabelHtml += `${element}`;
});
if (this.domainsLabelHtml.endsWith('>'))
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());
}
我找到了一个看起来像我最初遇到的问题的答案,但该解决方案不适用于我的情况:
Links not working in ng-bind-html
如果有人能向我解释并帮助我解决问题,我会很高兴。
谢谢
在注入 Html 代码后,您必须 运行 $compile(this.domainsLabelHtml)($scope);
,这应该由 Angular 管理。
编辑
我认为编译 this.domainsLabelHtml 可能行不通。尝试向应该绑定 Html 的跨度添加一个 Id 而不是:
//Html
<span id="id-of-span" ng-bind-html="TabsDomains.trustedHtml(TabsDomains.domainsLabelHtml)"></span>
//JS
$compile(angular.element('#id-of-span'))($scope);
我有一个 html 字符串,它是我在组件的控制器中动态构建的。这样:
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>>`;
else
this.domainsLabelHtml += `${element}`;
});
if (this.domainsLabelHtml.endsWith('>'))
this.domainsLabelHtml = this.domainsLabelHtml.slice(0, -5);
html代码:
<span ng-bind-html="TabsDomains.trustedHtml(TabsDomains.domainsLabelHtml)"></span>
我得到以下结果:
dynamicallyGeneratedCode
但是当我点击时没有任何反应。 由于没有任何效果,我手动写了一个 html 内容,如下所示:
<span><a position="0" ng-click="TabsDomains.goTo($event.target)">TEST</a>blabla</span>
我生成了以下结果 staticCode:
效果很好。
由于这两段代码在我看来完全一样,所以我不明白为什么动态生成的代码不起作用而静态代码却起作用。
这是受信任的 html 的代码:
public trustedHtml = function (plainText) {
return this.$sce.trustAsHtml(plainText);
}
我的 class 看起来像这样:
/// <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>>`;
else
this.domainsLabelHtml += `${element}`;
});
if (this.domainsLabelHtml.endsWith('>'))
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());
}
我找到了一个看起来像我最初遇到的问题的答案,但该解决方案不适用于我的情况:
Links not working in ng-bind-html
如果有人能向我解释并帮助我解决问题,我会很高兴。
谢谢
在注入 Html 代码后,您必须 运行 $compile(this.domainsLabelHtml)($scope);
,这应该由 Angular 管理。
编辑
我认为编译 this.domainsLabelHtml 可能行不通。尝试向应该绑定 Html 的跨度添加一个 Id 而不是:
//Html
<span id="id-of-span" ng-bind-html="TabsDomains.trustedHtml(TabsDomains.domainsLabelHtml)"></span>
//JS
$compile(angular.element('#id-of-span'))($scope);