AngularJS Como adicionar dinamicamente HTML e ligar ao controlador

Estou apenas começando com o angularJS e lutando para descobrir uma arquitetura apropriada para o que estou tentando fazer. Eu tenho um aplicativo de página única, mas o URL sempre deve permanecer o mesmo ; Eu não quero que o usuário possa navegar para qualquer rota além da raiz. No meu aplicativo, há um div principal que precisará hospedar visões diferentes. Quando uma nova visão é acessada, eu quero que ela assuma a exibição na div principal. As visualizações carregadas dessa maneira podem ser descartadas ou permanecer ocultas no DOM – estou interessado em ver como cada uma delas pode funcionar.

Eu cheguei a um exemplo de trabalho grosseiro do que estou tentando fazer. Veja o exemplo de trabalho aqui neste Plunk. Basicamente eu quero carregar dinamicamente o HTML no DOM e ter os controladores padrão angularJS capazes de se conectar a esse novo HTML. Existe uma maneira melhor / mais simples de fazer isso do que usando a diretiva personalizada que eu tenho aqui e usando $ compile () para ligar para angular? Talvez haja algo parecido com o roteador, mas não exija que o URL tenha alterações para operar?

Aqui está a diretiva especial que estou usando até agora (tirada de outra postagem do 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); }); } }; }); 

Obrigado,

Andy

Eu usaria a diretiva ngInclude . No exemplo abaixo, você nem precisa escrever nenhum javascript. Os modelos podem facilmente viver em um URL remoto.

Aqui está uma demonstração de trabalho: http://plnkr.co/edit/5ImqWj65YllaCYD5kX5E?p=preview

 

Select page content template via dropdown

Set page content template via button click

Existe um outro caminho também

  1. etapa 1: crie um arquivo sample.html
  2. passo 2: crie uma tag div com algum id = loadhtml Por exemplo:

  3. passo 3: em qualquer controlador

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

Isso vai carregar uma página html na página atual

Para aqueles que, como eu, não tiveram a possibilidade de usar diretivas angulares e estavam “presos” fora do escopo angular, aqui está algo que pode ajudá-lo.

Após horas pesquisando na web e no documento angular, criei uma class que compila o HTML, coloca-o dentro de um alvo e vincula-o a um escopo ( $rootScope se não houver nenhum $scope para esse elemento)

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

Cobriu todos os meus casos, mas se você encontrar algo que eu deva adicionar a ele, sinta-se à vontade para comentar ou editar.

Espero que ajude.

Veja se este exemplo fornece algum esclarecimento. Basicamente, você configura um conjunto de rotas e inclui modelos parciais com base na rota. Definir ng-view no seu principal index.html permite injetar essas visualizações parciais.

A parte de configuração é assim:

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

O ponto de input para injetar a vista parcial em seu modelo principal é:

 

Eu precisava executar uma diretiva APÓS carregar vários modelos, então criei esta diretiva:

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