데이터베이스에서 동적 HTML 문자열 컴파일
그 상황
Angular 앱 내에는 ng-bind-html-unsafe 속성을 가진 div를 포함하는 컨트롤러가 지원하는 Page라는 지시문이 중첩되어 있습니다. 이것은 'pageContent'라는 $ scope var에 할당됩니다. 이 var는 데이터베이스에서 동적으로 생성 된 HTML을 할당받습니다. 사용자가 다음 페이지로 넘어 가면 DB에 대한 호출이 이루어지고 pageContent var가이 새로운 HTML로 설정되어 ng-bind-html-unsafe를 통해 화면에 렌더링됩니다. 코드는 다음과 같습니다.
페이지 지시문
angular.module('myApp.directives')
.directive('myPage', function ($compile) {
return {
templateUrl: 'page.html',
restrict: 'E',
compile: function compile(element, attrs, transclude) {
// does nothing currently
return {
pre: function preLink(scope, element, attrs, controller) {
// does nothing currently
},
post: function postLink(scope, element, attrs, controller) {
// does nothing currently
}
}
}
};
});
페이지 지시문 템플릿 (위의 templateUrl 속성의 "page.html")
<div ng-controller="PageCtrl" >
...
<!-- dynamic page content written into the div below -->
<div ng-bind-html-unsafe="pageContent" >
...
</div>
페이지 컨트롤러
angular.module('myApp')
.controller('PageCtrl', function ($scope) {
$scope.pageContent = '';
$scope.$on( "receivedPageContent", function(event, args) {
console.log( 'new page content received after DB call' );
$scope.pageContent = args.htmlStrFromDB;
});
});
작동합니다. 브라우저에서 DB의 페이지 HTML이 멋지게 렌더링되는 것을 볼 수 있습니다. 사용자가 다음 페이지로 넘어 가면 다음 페이지의 내용 등이 표시됩니다. 여태까지는 그런대로 잘됐다.
문제
여기서 문제는 페이지 내용 내에 대화 형 내용을 포함하려는 것입니다. 예를 들어, HTML은 사용자가 그것을 클릭 할 때 팝업 모달 창을 표시하는 것과 같은 멋진 작업을 수행하는 축소판 이미지를 포함 할 수 있습니다. 데이터베이스의 HTML 문자열에 Angular 메소드 호출 (ng-click)을 배치했지만 물론 Angular는 HTML 문자열을 구문 분석하고 인식하여 컴파일하지 않으면 메소드 호출이나 지시문을 인식하지 못합니다.
우리의 DB에서
1 페이지 내용 :
<p>Here's a cool pic of a lion. <img src="lion.png" ng-click="doSomethingAwesone('lion', 'showImage')" > Click on him to see a large image.</p>
2 페이지 내용 :
<p>Here's a snake. <img src="snake.png" ng-click="doSomethingAwesone('snake', 'playSound')" >Click to make him hiss.</p>
Page 컨트롤러로 돌아가서 해당 $ scope 함수를 추가합니다 :
페이지 컨트롤러
$scope.doSomethingAwesome = function( id, action ) {
console.log( "Going to do " + action + " with "+ id );
}
I can't figure out how to call that 'doSomethingAwesome' method from within the HTML string from the DB. I realize Angular has to parse the HTML string somehow, but how? I've read vague mumblings about the $compile service, and copied and pasted some examples, but nothing works. Also, most examples show dynamic content only getting set during the linking phase of the directive. We would want Page to stay alive throughout the life of the app. It constantly receives, compiles and displays new content as the user flips through pages.
In an abstract sense, I guess you could say we are trying to dynamically nest chunks of Angular within an Angular app, and need to be able to swap them in and out.
I've read various bits of Angular documentation multiple times, as well as all sorts of blog posts, and JS Fiddled with people's code. I don't know whether I'm completely misunderstanding Angular, or just missing something simple, or maybe I'm slow. In any case, I could use some advice.
ng-bind-html-unsafe
only renders the content as HTML. It doesn't bind Angular scope to the resulted DOM. You have to use $compile
service for that purpose. I created this plunker to demonstrate how to use $compile
to create a directive rendering dynamic HTML entered by users and binding to the controller's scope. The source is posted below.
demo.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js@1.0.7" data-semver="1.0.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js"></script>
<script src="script.js"></script>
</head>
<body>
<h1>Compile dynamic HTML</h1>
<div ng-controller="MyController">
<textarea ng-model="html"></textarea>
<div dynamic="html"></div>
</div>
</body>
</html>
script.js
var app = angular.module('app', []);
app.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function(html) {
ele.html(html);
$compile(ele.contents())(scope);
});
}
};
});
function MyController($scope) {
$scope.click = function(arg) {
alert('Clicked ' + arg);
}
$scope.html = '<a ng-click="click(1)" href="#">Click me</a>';
}
In angular 1.2.10 the line scope.$watch(attrs.dynamic, function(html) {
was returning an invalid character error because it was trying to watch the value of attrs.dynamic
which was html text.
I fixed that by fetching the attribute from the scope property
scope: { dynamic: '=dynamic'},
My example
angular.module('app')
.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
scope: { dynamic: '=dynamic'},
link: function postLink(scope, element, attrs) {
scope.$watch( 'dynamic' , function(html){
element.html(html);
$compile(element.contents())(scope);
});
}
};
});
Found in a google discussion group. Works for me.
var $injector = angular.injector(['ng', 'myApp']);
$injector.invoke(function($rootScope, $compile) {
$compile(element)($rootScope);
});
You can use
ng-bind-html https://docs.angularjs.org/api/ng/service/$sce
directive to bind html dynamically. However you have to get the data via $sce service.
Please see the live demo at http://plnkr.co/edit/k4s3Bx
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope,$sce) {
$scope.getHtml=function(){
return $sce.trustAsHtml("<b>Hi Rupesh hi <u>dfdfdfdf</u>!</b>sdafsdfsdf<button>dfdfasdf</button>");
}
});
<body ng-controller="MainCtrl">
<span ng-bind-html="getHtml()"></span>
</body>
Try this below code for binding html through attr
.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
scope: { dynamic: '=dynamic'},
link: function postLink(scope, element, attrs) {
scope.$watch( 'attrs.dynamic' , function(html){
element.html(scope.dynamic);
$compile(element.contents())(scope);
});
}
};
});
Try this element.html(scope.dynamic); than element.html(attr.dynamic);
참고URL : https://stackoverflow.com/questions/18157305/compiling-dynamic-html-strings-from-database
'development' 카테고리의 다른 글
Pyflakes가 문장을 무시하도록하려면 어떻게해야합니까? (0) | 2020.06.30 |
---|---|
Xcode에서 특정 소스 파일의 모든 경고를 억제하는 방법은 무엇입니까? (0) | 2020.06.30 |
캐시 지우기가있는 window.location.reload (0) | 2020.06.30 |
postgres를 사용하여 간격을 여러 시간으로 어떻게 변환합니까? (0) | 2020.06.30 |
활성 화면 크기를 얻으려면 어떻게해야합니까? (0) | 2020.06.30 |