在AngularJS服务调用之后填充jQuery UI手风琴
我正在尝试构建一个AngularJS应用程序,我正在使用jQuery UI手风琴控件。
问题是,jQuery UI手风琴是在我的AngularJS服务从服务器加载数据之前启动的。 换句话说:手风琴在启动时没有任何数据,因此不会显示何时填充AngularJS的数据。
该视图如下所示:
$("#b2b-line-accordion").togglepanels();
我的AngularJS控制器看起来像这样:
app.controller('orderController', function ($scope, orderService, userService) { // Constructor for this controller init(); function init() { $scope.selected = {}; $scope.totalSum = 0.00; $scope.shippingDate = ""; $scope.selectedShippingAddress = ""; $scope.orderComment = ""; $scope.agreements = false; $scope.passwordResetSuccess = false; $scope.passwordResetError = true; userService.getCurrentUser(2).then(function (response) { $scope.user = response.data; orderService.getProductCategoriesWithProducts($scope.user).then(function (d) { $scope.categories = d.data; }); }); } // Other methods omitted });
我的AngularJS服务看起来像这样:
app.service('orderService', function ($http) { this.getProductCategoriesWithProducts = function (user) { return $http.post('url to my service', user); }; }); app.service('userService', function ($http) { this.getCurrentUser = function(companyId) { return $http.get('url to my service' + companyId + '.aspx'); }; this.resetPassword = function() { return true; }; });
有没有办法告诉手风琴“等待”初始化,直到从服务返回数据? 🙂
提前致谢!
更新
我尝试链接方法并添加一些日志记录,似乎手风琴实际上是在从服务返回JSON之后启动的。
userService.getCurrentUser(2).then(function(response) { $scope.user = response.data; }).then(function() { orderService.getProductCategoriesWithProducts($scope.user).then(function(d) { $scope.categories = d.data; console.log("categories loaded"); }).then(function () { $("#b2b-line-accordion").accordion(); console.log("accordion loaded"); }); });
但是,它不显示手风琴:-(第一个手风琴div在生成的DOM中看起来很好:
但其余的标记(用角度数据绑定)并未启动。
完整标记:
{{ productCategory.CategoryName }}
Betegnelse Str. Enhed HF varenr. Antal Bemærkninger Beløb {{ product.ItemGroupName }} {{ product.ItemAttribute }} {{ product.ItemNumber }} Indtast venligst et tal {{ product.LinePrice | currency:"" }}
解
最后我找到了解决这个问题的方法! 我不完全确定它是否漂亮,如果它是Angular方式的东西(我猜它不是)
使用以下代码制定指令:
app.directive('accordion', function () { return { restrict: 'A', link: function ($scope, $element, attrs) { $(document).ready(function () { $scope.$watch('categories', function () { if ($scope.categories != null) { $element.accordion(); } }); }); } }; });
所以基本上当DOM准备就绪并且类别数组发生变化时(在数据加载时它会发生变化),我正在启动jQuery UI手风琴。
非常感谢@Sgoldy指点我这里正确的方向!
是的,你需要一个directive
,你可以处理这种更有棱角的方式!
在HTML
定义指令
从您的service
退回promise
并将promise
传递给指令。
在控制器中
$scope.accordionData = myService.getAccordionData();
ui-accordion
指令看起来像
.directive('uiAccordion', function($timeout) { return { scope:{ myAccordionData: '=uiAccordion' }, template: '', link: function(scope, element) { scope.myAccordionData.then(function(data) { scope.myData = data; generateAccordion(); }); var generateAccordion = function() { $timeout(function() { //<--- used $timeout to make sure ng-repeat is REALLY finished $(element).accordion({ header: "> div > h3" }); }); } } } })
当您的服务呼叫成功时,您将创建您的手风琴。 在这里你可以定义自己的accordion-template
模板与模型数据myData
绑定。 我在模板中使用ng-repeat
来创建accordion-header
和accordion-body
HTML
。
在generateAccordion
方法中,我使用$timeout
来确保ng-repeat
真正完成渲染,因为$timeout
将在当前摘要周期结束时执行。
检查演示
我的最佳实践是在启动控制器之前解决异步服务。
正如您在文档中看到的那样, http: //docs.angularjs.org/api/ngRoute。$ routeProvider
resolve – {Object。=} – 应该注入控制器的可选依赖关系映射。 如果这些依赖项中的任何一个是promise,路由器将等待它们全部被解析或者在实例化控制器之前被拒绝。 如果成功解析了所有promise,则会注入已解析的promise的值,并触发$ routeChangeSuccess事件。 如果任何promise被拒绝,则触发$ routeChangeError事件。
在解决或拒绝服务之前,您的控制器和视图甚至不会启动。
有一个很好的video教程, https://egghead.io/lessons/angularjs-resolve
在您的情况下,您可以配置如下所示的路由
var myApp = angular.module('myApp', ['ngRoute']); myApp.config(function($routeProvider) { $routeProvider.when('/', { templateUrl: 'main.html', controller: orderController, resolve: { categories: function(orderService) { return orderService.getProductCategoriesWithProducts(); }, user: function(userService) { return userService.getCurrentUser(); } } });
然后,与您的控制器
app.controller('orderController', function($scope, categories, user) { //categories and user is always here, so use it. });
我也在这里找到了类似的问题和答案