83 votes

AngularJS - Comment puis-je créer un nouveau scope isolé de manière programmatique ?

Je veux créer une AlertFactory avec Angular.factory. J'ai défini un template html comme suit

var template = "<h1>{{title}}</h1>";

Le titre est fourni par le contrôleur appelant et appliqué comme suit

var compiled = $compile(template)(scope);
body.append(compiled);

Alors, comment puis-je passer un champ d'application isolé du contrôleur à la fabrique ? J'utilise le code suivant dans le contrôleur

AlertFactory.open($scope);

Mais $scope est une variable globale du contrôleur. Je veux juste passer un petit scope pour la fabrique avec seulement la propriété title.

Nous vous remercions.

110voto

Alex Osborn Points 2756

Vous pouvez créer un nouveau champ d'application manuellement.

Vous pouvez créer un nouveau champ d'application à partir de $rootScope si vous l'injectez, ou simplement à partir de la portée de votre contrôleur - cela ne devrait pas avoir d'importance puisque vous l'isolerez.

var alertScope = $scope.$new(true);
alertScope.title = 'Hello';

AlertFactory.open(alertScope);

L'essentiel est de passer true à $new qui accepte un paramètre pour isolate ce qui évite d'hériter de la portée du parent.

De plus amples informations sont disponibles à l'adresse suivante http://docs.angularjs.org/api/ng.$rootScope.Scope#$new

22voto

Mark Rajcok Points 85912

Si vous n'avez besoin que d'interpoler des choses, utilisez la fonction Interpoler au lieu de $compile, et alors vous n'aurez pas besoin d'un champ d'application :

myApp.factory('myService', function($interpolate) {
    var template = "<h1>{{title}}</h1>";
    var interpolateFn = $interpolate(template);
    return {
        open: function(title) {
            var html = interpolateFn({ title: title });
            console.log(html);
            // append the html somewhere
        }
    }
});

Contrôleur de test :

function MyCtrl($scope, myService) {
    myService.open('The Title');
}

Violon

2voto

Voici les étapes à suivre :

  1. Ajoutez votre HTML au DOM en utilisant var comiledHTML = angular.element(yourHTML);
  2. Créez un nouveau champ d'application si vous le souhaitez var newScope = $rootScope.$new();
  3. Appeler la fonction $comile() ; qui renvoie la fonction de lien var linkFun = $compile(comiledHTML);
  4. Lier le nouveau champ d'application en appelant linkFun var finalTemplate = linkFun(newScope);
  5. Ajoutez finalTemplate à votre DOM YourHTMLElemet.append(finalTemplate);

2voto

Richard Lin Points 33

Jetez un coup d'œil à mon plunkr. Je génère par programme une directive widget avec une directive render.

https://plnkr.co/edit/5T642U9AiPr6fJthbVpD?p=preview

angular
  .module('app', [])
  .controller('mainCtrl', $scope => $scope.x = 'test')
  .directive('widget', widget)
  .directive('render', render)

function widget() {
  return {
    template: '<div><input ng-model="stuff"/>I say {{stuff}}</div>'
  }
}

function render($compile) {
  return {
    template: '<button ng-click="add()">{{name}}</button><hr/>',
    link: linkFn
  }

  function linkFn(scope, elem, attr) {
    scope.name = 'Add Widget';
    scope.add = () => {
      const newScope = scope.$new(true);
      newScope.export = (data) => alert(data);
      const templ = '<div>' +
                      '<widget></widget>' +
                      '<button ng-click="export(this.stuff)">Export</button>' +
                    '</div>';
      const compiledTempl = $compile(templ)(newScope);
      elem.append(compiledTempl);
    }
  }
}

1voto

rgaskill Points 938

Je suppose que lorsque vous parlez d'une portée d'isolement, vous parlez d'une directive.

Voici un exemple de la manière de procéder. http://jsfiddle.net/rgaskill/PYhGb/

var app = angular.module('test',[]);

app.controller('TestCtrl', function ($scope) {
    $scope.val = 'World';
});

app.factory('AlertFactory', function () {

    return {
        doWork: function(scope) {
            scope.title = 'Fun';    
            //scope.title = scope.val;  //notice val doesn't exist in this scope
        }
    };

});

app.controller('DirCtrl', function ($scope, AlertFactory) {
    AlertFactory.doWork($scope);  
});

app.directive('titleVal',function () {
    return {
        template: '<h1>Hello {{title}}</h1>',
        restrict: 'E',
        controller: 'DirCtrl',
        scope: {
            title: '='
        },
        link: function() {

        }
    };

});

En fait, il s'agit d'attacher un contrôleur à une directive qui a défini un champ d'application "isolate". La portée injectée dans le contrôleur de la directive sera une portée isolée. Dans le contrôleur de la directive, vous pouvez injecter votre AlertFactory avec lequel vous pouvez passer la portée isolée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X