AngularJS comment ajouter dynamiquement du HTML et lier au contrôleur

je commence juste avec angularJS et je lutte pour trouver une architecture appropriée pour ce que j'essaie de faire. J'ai une application d'une seule page mais L'URL doit toujours rester la même ; Je ne veux pas que l'utilisateur soit en mesure de naviguer vers des routes au-delà de la racine. Dans mon application, il y a une div principale qui aura besoin d'héberger des vues différentes. Quand on accède à une nouvelle vue, je veux qu'elle prenne le contrôle de l'affichage dans la div principale. Les vues chargées de cette façon peuvent être jeter ou rester comme caché dans le DOM - je suis intéressé à voir comment chacun pourrait fonctionner.

j'ai trouvé un exemple grossier de ce que j'essaie de faire. voir Exemple de travail ici dans ce Plunk. fondamentalement je veux charger dynamiquement HTML dans le DOM et avoir des contrôleurs angularJS standard être en mesure de s'accrocher dans ce nouveau HTML. Y a-t-il un moyen plus simple de le faire qu'en utilisant la directive personnalisée que j'ai ici et en utilisant $compiler() pour connecter angulaire? Peut-être qu'il y a quelque chose comme le routeur, mais ne nécessite pas de changements D'URL pour fonctionner?

Voici la directive spéciale que j'utilise jusqu'à présent (tirée d'un autre SO post):

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

Merci,

Andy

56
demandé sur Andy 2013-11-08 00:24:20

5 réponses

j'utiliserais la directive intégrée ngInclude . Dans l'exemple ci-dessous, vous n'avez même pas besoin d'écrire du javascript. Les modèles peuvent tout aussi facilement vivre à une url distante.

Voici une démo de travail: http://plnkr.co/edit/5ImqWj65YllaCYD5kX5E?p=preview

<p>Select page content template via dropdown</p>
<select ng-model="template">
    <option value="page1">Page 1</option>
    <option value="page2">Page 2</option>
</select>

<p>Set page content template via button click</p>
<button ng-click="template='page2'">Show Page 2 Content</button>

<ng-include src="template"></ng-include>

<script type="text/ng-template" id="page1">
    <h1 style="color: blue;">This is the page 1 content</h1>
</script>

<script type="text/ng-template" id="page2">
    <h1 style="color:green;">This is the page 2 content</h1>
</script>
64
répondu jessegavin 2016-03-31 03:59:05

il y a une autre façon aussi

  1. étape 1: créer un échantillon.fichier html
  2. étape 2: Créer une balise div avec un certain id = loadhtml Eg: <div id="loadhtml"></div>
  3. étape 3: dans toute Contrôleur

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

ceci chargera une page html dans la page courante

16
répondu varun joshi 2017-08-23 13:28:38

pour ceux, comme moi, qui n'avaient pas la possibilité d'utiliser la directive angulaire et étaient "coincés" en dehors de la portée angulaire, voici quelque chose qui pourrait vous aider.

après des heures de recherche sur le web et sur le doc angulaire, j'ai créé une classe qui compile HTML, le place à l'intérieur d'une cible, et le lie à une portée ( $rootScope s'il n'y a pas de $scope pour cet élément)

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

il couvrait tous mes cas, mais si vous trouvez quelque chose que je devrais ajouter, n'hésitez pas à commenter ou modifier.

j'Espère que ça aidera.

12
répondu RPDeshaies 2015-02-27 13:24:21

voir si cet exemple apporte des précisions. Fondamentalement, vous configurez un ensemble de routes et incluez des gabarits partiels basés sur la route. Définir ng-view dans votre index principal.html vous permet d'injecter ces vues partielles.

la partie de configuration ressemble à ceci:

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

le point d'entrée pour l'injection de la vue partielle dans votre modèle principal est:

<div class="container" ng-view=""></div>
2
répondu Stuart 2013-11-07 22:05:02

j'avais besoin d'exécuter une directive après avoir chargé plusieurs gabarits et j'ai donc créé cette directive:

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>
2
répondu TekTimmy 2015-06-01 10:43:12