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 ответов:
Я бы использовал встроенный
ngInclude
есть и другой путь
- Шаг 1: Создайте образец.html файл
- Шаг 2: Создайте тег div с некоторым id=loadhtml например:
<div id="loadhtml"></div>
Шаг 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>