web-dev-qa-db-fra.com

AngularJS - Comment puis-je créer par programme une nouvelle étendue isolée?

Je veux créer un AlertFactory avec Angular.factory. J'ai défini un modèle HTML comme suit

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

Le titre est fourni par le contrôleur d’appel et appliqué comme suit

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

Alors, comment puis-je passer de la portée isolée du contrôleur à l’usine? J'utilise dans le code de suivi du contrôleur

AlertFactory.open($scope);

Mais $ scope est une variable d’étendue du contrôleur global. Je veux juste passer une petite portée pour l’usine avec juste la propriété du titre.

Merci.

80
Premier

Vous pouvez créer une nouvelle étendue manuellement.

Vous pouvez créer une nouvelle portée à 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 allez le rendre isolé.

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

AlertFactory.open(alertScope);

La clé ici passe true à $new, qui accepte un paramètre pour isolate, ce qui évite d’hériter de la portée du parent.

Plus d'informations peuvent être trouvées à: http://docs.angularjs.org/api/ng.$rootScope.Scope#$new

106
Alex Osborn

Si vous avez seulement besoin d'interpoler des choses, utilisez le service $ interpolate au lieu de $ compile. Vous n'aurez alors pas besoin d'une portée:

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

22
Mark Rajcok

vérifier mon plunkr. Je génère par programme une directive de widget avec une directive de rendu.

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);
    }
  }
}
2
Richard Lin

Les étapes suivantes sont les suivantes:

  1. Ajoutez votre code HTML au DOM en utilisant var comiledHTML = angular.element(yourHTML);
  2. Créez une nouvelle étendue si vous voulez var newScope = $rootScope.$new();
  3. Appelez $ comile (); fonction qui renvoie la fonction de liaison var linkFun = $compile(comiledHTML);
  4. Liez la nouvelle portée en appelant linkFun var finalTemplate = linkFun(newScope);
  5. Ajouter finalTemplate à votre DOM YourHTMLElemet.append(finalTemplate);
2

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

Voici un exemple de la façon de le faire. 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() {

        }
    };

});

Fondamentalement, attachez un contrôleur à une directive qui a défini une portée d'isolement. La portée injectée dans le contrôleur de directive sera une portée isolée. Dans le contrôleur de directive, vous pouvez injecter votre AlertFactory avec laquelle vous pouvez passer le scope isolate.

1
rgaskill