Populate jQuery UI accordion after AngularJS service call

前端 未结 2 439
执念已碎
执念已碎 2020-12-14 23:11

I\'m currently trying to build an AngularJS app where I\'m using a jQuery UI accordion control.

The problem is, that the jQuery UI accordion is initiated before<

相关标签:
2条回答
  • 2020-12-15 00:10

    Yes you need a directive and you can handle this more angular way !

    In HTML define the directive

    <div ui-accordion="accordionData" ></div>
    

    Return promise from your service and pass the promise to the directive.

    In controller

    $scope.accordionData = myService.getAccordionData();
    

    The ui-accordion directive looks like

    .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"
            });
           });
         }
       }
      }
    })
    

    When your service call succeed then you create your accordion. Here you can define your own accordion-template like

    <div ng-repeat="item in myData">
      <h3 ng-bind="item.title"></h3>
      <div>
         <p ng-bind="item.data"></p>
      </div>
    </div>
    

    Template binds with your model data myData. I use ng-repeat inside the template to create accordion-header and accordion-body HTML.

    In the generateAccordion method i use $timeout to make sure the ng-repeat is really finished rendering because $timeout will execute at the end of the current digest cycle.

    Check the Demo

    0 讨论(0)
  • 2020-12-15 00:13

    My best practice is to resolve your asynchronous services before controller is initiated.

    As you can see in the document, http://docs.angularjs.org/api/ngRoute.$routeProvider

    resolve - {Object.=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated. If all the promises are resolved successfully, the values of the resolved promises are injected and $routeChangeSuccess event is fired. If any of the promises are rejected the $routeChangeError event is fired.

    Your controller and view won't be even started before your service is resolved or rejected.

    There is a good video tutorial about this, https://egghead.io/lessons/angularjs-resolve

    In your case, you can config routes like the following

    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();
          }
        }
      });
    

    Then, with your controller

    app.controller('orderController', function($scope, categories, user) {
       //categories and user is always here, so use it.
    });
    

    I have also found a similar question and answer here

    0 讨论(0)
提交回复
热议问题