我目前正在尝试构建一个使用jQuery UI手风琴控件的AngularJS应用程序。
问题是, 在 我的AngularJS服务完成从服务器加载数据 之前 启动了jQuery UI手风琴。换句话说:手风琴启动时没有任何数据,因此填充来自AngularJS的数据时也不会显示。
该视图如下所示:
<!-- Pretty standard accordion markup omitted --> $("#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中看起来不错:
<div id="b2b-line-accordion" class="ui-accordion ui-widget ui-helper-reset" role="tablist"> ... </div>
但是其余的标记(与角度进行数据绑定)未启动。
完整标记:
<div id="b2b-line-accordion"> <div ng-repeat="productCategory in categories"> <h3>{{ productCategory.CategoryName }}</h3> <div class="b2b-line-wrapper"> <table> <tr> <th>Betegnelse</th> <th>Str.</th> <th>Enhed</th> <th>HF varenr.</th> <th>Antal</th> <th>Bemærkninger</th> <th>Beløb</th> </tr> <tr ng-repeat="product in productCategory.Products"> <td>{{ product.ItemGroupName }}</td> <td>{{ product.ItemAttribute }}</td> <td> <select ng-model="product.SelectedVariant" ng-options="variant as variant.VariantUnit for variant in product.Variants" ng-init="product.SelectedVariant = product.Variants[0]" ng-change="calculateLinePrice(product); calculateTotalPrice();"> </select> </td> <td>{{ product.ItemNumber }}</td> <td class="line-amount"> <span class="ensure-number-label" ng-show="product.IsNumOfSelectedItemsValid">Indtast venligst et tal</span> <input type="number" class="line-amount" name="amount" min="0" ng-change="ensureNumber(product); calculateLinePrice(product); calculateTotalPrice();" ng-model="product.NumOfSelectedItems" value="{{ product.NumOfSelectedItems }}" /> <td> <input type="text" name="line-comments" ng-model="product.UserComment" value="{{ product.UserComment }}" /></td> <td><span class="line-sum">{{ product.LinePrice | currency:"" }}</span></td> </tr> </table> </div> </div> </div>
解
终于我找到了解决方法!我不确定是不是很漂亮,是否是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准备就绪时,当category数组发生更改时(数据加载后即会执行此操作),我将启动jQuery UI手风琴。
非常感谢@Sgoldy在这里向我指出正确的方向!
是的,您需要一个,directive并且您可以处理这种更加棱角分明的方式!
directive
中HTML定义指令
HTML
<div ui-accordion="accordionData" ></div>
promise从您返回service并将传递promise给指令。
promise
service
在控制器中
$scope.accordionData = myService.getAccordionData();
该ui-accordion指令看起来像
ui-accordion
.directive('uiAccordion', function($timeout) { return { scope:{ myAccordionData: '=uiAccordion' }, template: '<div ng-repeat="item in myData"><h3 ng-bind="item.title"></h3><div><p ng-bind="item.data"></p></div></div>', 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" }); }); } } } })
服务电话成功后,then您就可以创建手风琴了。在这里您可以定义自己的accordion-template喜欢
then
accordion-template
<div ng-repeat="item in myData"> <h3 ng-bind="item.title"></h3> <div> <p ng-bind="item.data"></p> </div> </div>
模板与您的模型数据绑定myData。我ng-repeat在模板内部使用创建accordion-header和accordion-body HTML。
myData
ng-repeat
accordion-header
accordion-body
在此generateAccordion方法中,我将使用$timeout来确保ng- repeat真正完成渲染,因为$timeout它将在当前摘要周期的末尾执行。
generateAccordion
$timeout
ng- repeat
检查 [**Demo**](http://plnkr.co/edit/PPXyIfNnDFCXwfKLRySp?p=preview)
[**Demo**](http://plnkr.co/edit/PPXyIfNnDFCXwfKLRySp?p=preview)