Как стать автором
Обновить

Angular XSLT module

Время на прочтение4 мин
Количество просмотров8.9K
Недавно мне попался маленький проект, где я предложил использование Angular и XSLT, на что я получил такой вопрос: «С чего бы использовать устаревшую технологию XSLT, ведь ее используют только с Java, да к тому же, только для Enterprise»?

Этот вопрос и явился причиной того, что я решил написать данную статью.

Итак, разрешите представить вашему вниманию «химеру» под названием Angular XSLT module. Ангулар разделяет business логику и view логику, но с модулем XSLT, view логику Angular можно вообще отдать XSLT.

Есть конечно пара подводных камней, это:

1) Результат не будет рендерится,
2) Angular команды не будут вызываться.

Но легким движением руки, эти проблемы решаются на раз-два!

Итак, начнем.

Имеет следующий код:

<html>
	<body ng-app="app">
		<div ng-controller="ExampleController">
			<pre>{{xml | xslt:xslt}}</pre>
		</div>
		<script src="angular.js"></script>
		<script src="ng-xslt.js"></script>
		<script>
		    var myApp = angular.module('app', ['ngXslt']);

			myApp.controller('ExampleController', ['$scope',function ($scope) {
				$scope.xml  ='<?xml version="1.0" encoding="UTF-8"?><root><name>Angular XSLT module!</name></root>';
				$scope.xslt = '<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet  xmlns:xsl= "http://www.w3.org/1999/XSL/Transform"  version="1.0"><xsl:output method="html"/><xsl:template match="/"><xsl:text>Hello, my name is </xsl:text><b><xsl:value-of select="root/name"/></b></xsl:template></xsl:stylesheet>';
				}
			]);
		</script>
	</body>
</html>

(Заметьте, XSLT используется в качестве фильтра.)

Что в браузере рендерится как:

Hello, my name is < b xmlns=«www.w3.org/1999/xhtml»>Angular XSLT module!</b >

Негоже… Нет рендеринга, и выводится как текст. Добавляем одно легкое движение рукой, что называется «санитаризация (trustAsHtml(htmlCode))»:

<html>
	<body ng-app="app">
		<div ng-controller="ExampleController">
			<div ng-bind-html="xml | xslt:xslt | sanitize"></div>
		</div>
		<script src="angular.js"></script>
		<script src="ng-xslt.js"></script>
		<script>
		    var myApp = angular.module('app', ['ngXslt']);

			myApp.controller('ExampleController', ['$scope',function ($scope) {
				$scope.xml  ='<?xml version="1.0" encoding="UTF-8"?><root><name>Angular XSLT module!</name></root>';
				$scope.xslt = '<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet  xmlns:xsl= "http://www.w3.org/1999/XSL/Transform"  version="1.0"><xsl:output method="html"/><xsl:template match="/"><xsl:text>Hello, my name is </xsl:text><b><xsl:value-of select="root/name"/></b></xsl:template></xsl:stylesheet>';
				}
			]);
			myApp.filter("sanitize", ['$sce', function($sce) {
			  return function(htmlCode){
			    return $sce.trustAsHtml(htmlCode);
			  }
			}]);
		</script>
	</body>
</html>


Что в браузере будет как:

Hello, my name is Angular XSLT module!

Где «Angular XSLT module!» рендерится в bold.

Теперь попытаемся вызвать функцию Ангулара из текста, который выдает нам XSLT модуль, для чего мы:

1) Естественно, дописываем в XSLT вызов функции «clickMyXslt()».
2) В Angular дописываем соответствующую функцию.
3) В Angular дописываем директиву(compileTemplate) для компиляции текста, который выдает нам XSLT модуль.

<html>
	<body ng-app="app">
		<div ng-controller="ExampleController">
			<div ng-bind-html="xml | xslt:xslt | sanitize" compile-template></div>
		</div>
		<script src="angular.js"></script>
		<script src="ng-xslt.js"></script>
		<script>
		    var myApp = angular.module('app', ['ngXslt']);

			myApp.controller('ExampleController', ['$scope',function ($scope) {
					$scope.xml  ='<?xml version="1.0" encoding="UTF-8"?><root><name>Angular XSLT module!</name></root>';
					$scope.xslt = '<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet  xmlns:xsl= "http://www.w3.org/1999/XSL/Transform"  version="1.0" ><xsl:output method="html"/><xsl:template match="/"><xsl:text>Hello, my name is </xsl:text><b><xsl:value-of select="root/name"/></b><input type="button" ng-click="clickMyXslt()" value="clickMyXslt"/></xsl:template></xsl:stylesheet>';
					$scope.clickMyXslt = function() {
						alert("Yes, I am from clickMyXslt function!");
					};
				}
			]);
			myApp.filter("sanitize", ['$sce', function($sce) {
			  return function(htmlCode){
			    return $sce.trustAsHtml(htmlCode);
			  }
			}]);

			myApp.directive('compileTemplate', function($compile, $parse){
			    return {
			        link: function(scope, element, attr){
			            var parsed = $parse(attr.ngBindHtml);
			            function getStringValue() { return (parsed(scope) || '').toString(); }
			            //Recompile if the template changes
			            scope.$watch(getStringValue, function() {
			                $compile(element, null, -9999)(scope);  //The -9999 makes it skip directives so that we do not recompile ourselves
			            });
			        }
					
			    }
			});

		</script>
	</body>
</html>

Что результатирует в браузере:

Hello, my name is Angular XSLT module! <button>clickMyXslt</button>

Где, кликнув на <button/>, получаем всплывающее JS окошко:

alert(«Yes, I am from clickMyXslt function!»);

На этом все. Надеюсь по немногу мифы об устаревании XSLT станут мифами.

(*Все эти техники не я сам придумал, а выловил в интернете и соединил в одно)

Удачного всем кода!

PS: Пример такого подхода можно посмотреть здесь (видеоролик в VK).

PSS: Здесь используется AngularJS v1.4.0
Теги:
Хабы:
Всего голосов 27: ↑20 и ↓7+13
Комментарии30

Публикации

Истории

Работа

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
14 сентября
Конференция Practical ML Conf
МоскваОнлайн
19 сентября
CDI Conf 2024
Москва
20 – 22 сентября
BCI Hack Moscow
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
25 сентября
Конференция Yandex Scale 2024
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн