AngularJS как динамически добавить HTML и привязать к контроллеру


Я только начинаю с angularJS и изо всех сил пытаюсь выяснить правильную архитектуру для того, что я пытаюсь сделать. У меня есть одна страница приложения, но URL всегда должен оставаться тем же; Я не хочу, чтобы пользователь мог перемещаться по любым маршрутам за пределами корня. В моем приложении есть один основной div, который должен будет размещать разные представления. Когда новый вид доступен, я хочу, чтобы он взял на себя отображение в главном div. Виды, загруженные таким образом, могут быть выброшены или придерживаться вокруг, как скрыто в DOM-мне интересно посмотреть, как каждый из них может работать.

Я придумал грубый рабочий пример того, что я пытаюсь сделать. см. рабочий пример здесь в этом Plunk. в основном я хочу динамически загружать HTML в DOM и иметь стандартные контроллеры angularJS, которые могут подключаться к этому новому HTML. Есть ли лучший / более простой способ сделать это, чем используя пользовательскую директиву, которую я здесь имею, и используя $compile() для подключения к angular? Возможно есть что-то вроде маршрутизатора, но не требует изменения URL для работы?

вот специальная директива, которую я использую до сих пор (взято из другого сообщения SO):

// Stolen from: http://stackoverflow.com/questions/18157305/angularjs-compiling-dynamic-html-strings-from-database
myApp.directive('dynamic', function ($compile) {
  return {
    replace: true,
    link: function (scope, ele, attrs) {
      scope.$watch(attrs.dynamic, function(html) {
        if (!html) {
            return;
        }
        ele.html((typeof(html) === 'string') ? html : html.data);
        $compile(ele.contents())(scope);
      });
    }
  };
});

спасибо,

Энди

5 56

5 ответов:

Я бы использовал встроенный ngInclude

есть и другой путь

  1. Шаг 1: Создайте образец.html файл
  2. Шаг 2: Создайте тег div с некоторым id=loadhtml например:<div id="loadhtml"></div>
  3. Шаг 3: в любое Контроллер

        var htmlcontent = $('#loadhtml ');
        htmlcontent.load('/Pages/Common/contact.html')
        $compile(htmlcontent.contents())($scope);
    

это загрузит html-страницу в текущей странице

для тех, кто, как и я, не имел возможности использовать угловую директиву и был "застрял" за пределами угловой области, вот что может вам помочь.

после многочасового поиска в интернете и на угловом документе я создал класс, который компилирует HTML, помещает его внутри целей и привязывает его к области ($rootScope если нет $scope для этого элемента)

/**
 * AngularHelper : Contains methods that help using angular without being in the scope of an angular controller or directive
 */
var AngularHelper = (function () {
    var AngularHelper = function () { };

    /**
     * ApplicationName : Default application name for the helper
     */
    var defaultApplicationName = "myApplicationName";

    /**
     * Compile : Compile html with the rootScope of an application
     *  and replace the content of a target element with the compiled html
     * @$targetDom : The dom in which the compiled html should be placed
     * @htmlToCompile : The html to compile using angular
     * @applicationName : (Optionnal) The name of the application (use the default one if empty)
     */
    AngularHelper.Compile = function ($targetDom, htmlToCompile, applicationName) {
        var $injector = angular.injector(["ng", applicationName || defaultApplicationName]);

        $injector.invoke(["$compile", "$rootScope", function ($compile, $rootScope) {
            //Get the scope of the target, use the rootScope if it does not exists
            var $scope = $targetDom.html(htmlToCompile).scope();
            $compile($targetDom)($scope || $rootScope);
            $rootScope.$digest();
        }]);
    }

    return AngularHelper;
})();

он охватил все мои случаи, но если вы найдете что-то, что я должен добавить она, не стесняйтесь комментировать или редактировать.

надеюсь, что это поможет.

посмотреть, если предусматривает каких-либо разъяснений. В основном вы настраиваете набор маршрутов и включаете частичные шаблоны на основе маршрута. Установка ng-view в вашем основном индексе.html позволяет вводить эти частичные представления.

часть конфигурации выглядит так:

  .config(['$routeProvider', function($routeProvider) {
    $routeProvider
      .when('/', {controller:'ListCtrl', templateUrl:'list.html'})
      .otherwise({redirectTo:'/'});
  }])

точка входа для введения частичного представления в ваш основной шаблон:

<div class="container" ng-view=""></div>

мне нужно было выполнить директиву после загрузки нескольких шаблонов, поэтому я создал эту директиву:

utilModule.directive('utPreload',
    ['$templateRequest', '$templateCache', '$q', '$compile', '$rootScope',
    function($templateRequest, $templateCache, $q, $compile, $rootScope) {
    'use strict';
    var link = function(scope, element) {
        scope.$watch('done', function(done) {
            if(done === true) {
                var html = "";
                if(scope.slvAppend === true) {
                    scope.urls.forEach(function(url) {
                        html += $templateCache.get(url);
                    });
                }
                html += scope.slvHtml;
                element.append($compile(html)($rootScope));
            }
        });
    };

    var controller = function($scope) {
        $scope.done = false;
        $scope.html = "";
        $scope.urls = $scope.slvTemplate.split(',');
        var promises = [];
        $scope.urls.forEach(function(url) {
            promises.add($templateRequest(url));
        });
        $q.all(promises).then(
            function() { // SUCCESS
                $scope.done = true;
            }, function() { // FAIL
                throw new Error('preload failed.');
            }
        );
    };

    return {
        restrict: 'A',
        scope: {
            utTemplate: '=', // the templates to load (comma separated)
            utAppend: '=', // boolean: append templates to DOM after load?
            utHtml: '=' // the html to append and compile after templates have been loaded
        },
        link: link,
        controller: controller
    };
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>

<div class="container-fluid"
     ut-preload
     ut-append="true"
     ut-template="'html/one.html,html/two.html'"
     ut-html="'<my-directive></my-directive>'">
 
</div>