我将在Liferay Portal中使用全局AngularJS。因为,就像AngularJS的设计一样:
为什么选择AngularJS?HTML非常适合于声明静态文档,但是当我们尝试使用它来声明Web应用程序中的动态视图时,HTML却显得毫无用处。AngularJS允许您扩展应用程序的HTML词汇。由此产生的环境具有极强的表现力,可读性,并且可以快速开发。
通过开发Liferay-Theme和Portlet,我将简单地使用html的声明性语法。
为此,我创建了新的Liferay主题并自定义了以下内容portal_normal.vm
:
<!DOCTYPE html>
<#include init />
<html ... ng-app="liferay">
<head>
...
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js"></script>
<script type="text/javascript" src="${javascript_folder}/my.js" charset="utf-8"></script>
</head>
<body class="${css_class}">
<div ng-controller="LiferayCtrl">
在这里my.js
:
angular.module('liferay', [])
.controller('LiferayCtrl', function($scope) {
console.log("---==== Init AngularJS ====---");
$scope.Liferay = Liferay;
});
而且我可以扩展控制器,例如获得Liferay-Site名称。
这一切是为了什么?
因此,我可以通过声明性html语法简单地访问Liferay JavaScript值和函数,而无需像AngularJS那样直接调用JavaScript函数。
例如,现在可以通过声明性的html代码来获取Liferay JavaScript的值和功能,例如此处,以在Web内容显示中获取当前的url:
Liferay current URL: {{Liferay.currentURL}}
但是,我的问题是:
首先:在门户网站上使用AngularJS的好主意。到目前为止,我们仅将AngularJS用于portlet –我将在后面解释原因和方式。
与其他JavaScript库或框架一样,使用AngularJS不会产生更多副作用。Liferay随AlloyUi(http://alloyui.com/)一起提供。该JavaScript库基于yahoo编写的YUI(http://yuilibrary.com/)。YUI使用的名称空间不同于jQuery,因此您可以将jQuery与AlloyUI一起使用。而且,如果您能够使用jQuery而没有任何副作用,则可以使用AngularJS,因为AngularJS提供了jQuery的一个子集。
如果您不仅需要AngularJS的jqLite实现,还需要完整的jQuery,则只需确保在AngularJS之前包含jQuery。可以通过更改portal_normal.vm
主题中的来轻松完成此操作:
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>$the_title - $company_name</title>
<script type="text/javascript" src="$javascript_folder/jquery-2.0.3.min.js" charset="utf-8"></script>
<script type="text/javascript" src="$javascript_folder/angular-1.2.7.min.js" charset="utf-8"></script>
$theme.include($top_head_include)
</head>
如果在主题级别包含JavaScript文件,则可以为每个主题使用不同的版本。如果您有多个门户网站实例,并且没有机会在每个实例中使用相同的版本,则这非常方便。
这取决于。必须知道,如果将ng-app
指令放在html元素上,Angular将解析整个网页,如您的示例。如果您的页面很大,并且内容很多,则可能是性能问题。因此,最好将ngApp指令放到页面的下方,并通过以下方式手动初始化ngApp:
$().ready(function() {
angular.bootstrap("css-selector", ['yourApp']);
});
有两种方法可以实现此目的。
1)在您的示例中,在大ngApp上。您必须知道,您不能嵌套ngApps。因此,每个portlet必须是您应用程序的一部分。使用这种方法,您将失去Portlet可以为页面提供单独部分的可能性。所有portlet需要知道ngApp的名称,并且必须扩展此ngApp。如果这些portlet使用其他ngApp名称或不使用任何其他ngApp名称,则不得在未更改其他门户网站服务器的情况下使用它们。其优点是可以共享$rootScope
所有的门户和门户可以与角度的方式相互通信(例如$emit
,$on
共享servcies,...)。
2)每个portlet都有自己的ngApp。在这种情况下,没有依赖性。每个portlet都可以通过实例化其自己的ngApp angular.bootstrap
。此外,每个ngApp只会为一小部分网页创建,只有在确实需要时才创建。
两种方式都应避免使用路由。因为routeProvider
每页只能使用一个。
我们已决定使用第二种方法,以使Portlet保持独立并且不依赖于全局ngApp。
您知道可以配置您的portlet。因此出现了一个问题:“我该如何为我的有角度的portlet提供我的portlet首选项?” 当然,您可以发出http请求以获取它们。但这还不够,因为您拨打了不必要的电话。您的Portlet通常是Java服务器页面,因此最好在服务器的生成时间中包含首选项,并将这些信息提供给您的角度应用程序。但是如何?
在doView
portlet的方法中,您可以创建一个JSON对象并将其存储在您的密钥中RenderRequest
:
public void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException {
PortletPreferences prefs = renderRequest.getPreferences();
Map<String, Object> values = new HashMap<String, Object>();
values.put(key, value);
renderRequest.setAttribute("config", new ObjectMapper().writeValueAsString(values));
super.doView(renderRequest, renderResponse);
}
在您的jsp中,您可以访问以下配置属性:
<div class="hidden" portlet-config>${config}</div>
portlet-config
是解析JSON并将信息存储在服务实例中的指令:
.factory('portletConfigService', function(){ return {}})
.directive('portletConfig', ['portletConfigService', function(portletConfigService) {
return {
restrict: 'A',
compile: function(elem, attrs) {
var config = angular.fromJson(elem.text());
angular.forEach(config, function(value, key){
portletConfigService[key] = value;
});
}
};
}])
现在,您可以将注入portletConfigService
到每个控制器,服务,工厂或其他任何东西,并使用config参数:portletConfigService.key
。
我们遇到的另一个问题是语言属性。通常,您将在language.properties
文件中定义它们,并在jsp中使用它们。例如通过fmt:message
标签。但是您还希望能够在您的angular js应用程序中访问它们。而且,您绝对不希望在源中将它们包含两次。我们通过生成的服务和一条指令来解决此问题,该指令读取当前用户语言的属性并在jsp中创建有角度的东西:
<%@page contentType="text/javascript; charset=UTF-8" %>
<%@ page import="java.util.ResourceBundle" %>
<%@ page import="java.util.Locale" %>
<%@ page import="java.util.Enumeration" %>
<%@ page import="org.apache.commons.lang.StringEscapeUtils" %>
angular.module('translations', [])
.factory('translations', function(){ return {
<%
ResourceBundle labels = ResourceBundle.getBundle("language", request.getLocale());
Enumeration<String> keys = labels.getKeys();
while(keys.hasMoreElements()){
String key = keys.nextElement();
out.write("\""+key+"\":\""+StringEscapeUtils.escapeJavaScript(labels.getString(key))+"\"");
if(keys.hasMoreElements()){
out.write(",\n");
}
}
%>
}})
.filter('mpbtranslate', ['translations', function(translations) {
return function(input) {
var translation = translations[input];
return translation? translation: '???'+input+'???';
};
}]);
现在,您可以将这些翻译用作服务和过滤器。例如,<div>{{'title' | translate}}</div>
将在客户端被评估为“ Titel”。
希望您得到有关您所关注问题的有用信息。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句