AngularJS - Làm cách nào để tạo một phạm vi mới, riêng biệt theo lập trình?


81

Tôi muốn tạo một AlertFactory với Angular.factory. Tôi đã xác định một mẫu html như sau

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

Tiêu đề được cung cấp bởi bộ điều khiển cuộc gọi và áp dụng như sau

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

Vì vậy, làm thế nào tôi có thể chuyển phạm vi bị cô lập từ bộ điều khiển đến nhà máy? Tôi đang sử dụng mã theo dõi bộ điều khiển

AlertFactory.open($scope);

Nhưng $ scope là biến phạm vi bộ điều khiển toàn cầu. Tôi chỉ muốn vượt qua một phạm vi nhỏ cho nhà máy chỉ có thuộc tính tiêu đề.

Cảm ơn bạn.

Câu trả lời:


107

Bạn có thể tạo phạm vi mới theo cách thủ công.

Bạn có thể tạo một phạm vi mới $rootScopenếu bạn đưa nó vào hoặc chỉ từ phạm vi bộ điều khiển của bạn - điều này không quan trọng vì bạn sẽ làm cho nó bị cô lập.

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

AlertFactory.open(alertScope);

Khóa ở đây là chuyển truetới $new, chấp nhận một tham số cho isolate, điều này tránh kế thừa phạm vi từ cấp độ gốc.

Có thể tìm thêm thông tin tại: http://docs.angularjs.org/api/ng.$rootScope.Scope#$new


10
Nếu bạn tạo một phạm vi mới theo cách thủ công, có thể bạn cũng sẽ phải hủy nó theo cách thủ công. Thông thường tốt hơn là không tạo phạm vi theo cách thủ công.
Mark Rajcok

Tôi đã thực hiện một bài kiểm tra, nhưng nó không hoạt động. Vui lòng xem stackoverflow.com/questions/15565462/…
Premier

3
@MarkRajcok mà bạn đề cập rằng thông thường tốt hơn là không tạo phạm vi theo cách thủ công. Tuy nhiên, đâu là giải pháp thay thế nếu bạn cần tạo html động và muốn sử dụng chỉ thị góc trong html đó?
lostintranslation

Tiết kiệm cuộc sống! Phải làm điều này, vì tôi đang viết một trình bao bọc cho Angular Bootstrap Modal .
Jonathan

9
Khi bạn tạo phạm vi con (cô lập hoặc không cô lập), Angular sẽ tự động hủy phạm vi đó khi phạm vi cha của nó bị phá hủy. Vì vậy, trong ví dụ này, khi nào $scopebị hủy alertScopecũng sẽ tự động bị hủy. Vì vậy @MarkRajcok đây là một trường hợp sử dụng hoàn toàn hợp lệ và hoàn toàn an toàn.
jkjustjoshing

22

Nếu bạn chỉ cần nội suy mọi thứ, hãy sử dụng dịch vụ $ interpolate thay vì $ compile, và sau đó bạn sẽ không cần phạm vi:

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

Bộ điều khiển thử nghiệm:

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

Vĩ cầm


2
Sự khác biệt giữa $ compile và $ interpolate là gì? $ interpolate làm cho chỉ văn bản thay thế?
Premier

3
@Premier, đó là hiểu biết của tôi. Xem thêm stackoverflow.com/a/13460295/215945 Nếu mẫu của bạn chứa các lệnh thì $ interpolate sẽ không hoạt động - bạn cần sử dụng $ compile cho việc đó.
Mark Rajcok

Ok, cảm ơn bạn. Nó không phù hợp với nhiệm vụ của tôi, tôi cần một bộ điều khiển với phạm vi hoàn chỉnh.
Premier

1
@Premier, tôi khuyên bạn nên thử tạo một trò chơi điện tử hoặc thử nghiệm những gì bạn đang thử. Không rõ phạm vi cô lập của bạn đến từ đâu.
Mark Rajcok

Ồ vâng, tôi đã thực hiện một stackoverflow.com/questions/15565462/...
Premier

2

Tiếp theo là các bước:

  1. Thêm HTML của bạn vào DOM bằng cách sử dụng var comiledHTML = angular.element(yourHTML);
  2. Tạo một Phạm vi mới nếu bạn muốn var newScope = $rootScope.$new();
  3. Gọi $ comile (); hàm trả về hàm liên kếtvar linkFun = $compile(comiledHTML);
  4. Ràng buộc phạm vi mới bằng cách gọi linkFun var finalTemplate = linkFun(newScope);
  5. Nối finalTemplate vào DOM của bạn YourHTMLElemet.append(finalTemplate);

1
Từ var linkFun = $compile(comiledHTML);bước 2
iamdevlinph

2

kiểm tra plunkr của tôi. Tôi đang lập trình tạo một chỉ thị tiện ích con với một chỉ thị hiển thị.

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

1

Tôi giả sử khi bạn đang nói về một phạm vi cô lập, bạn đang nói về một chỉ thị.

Đây là một ví dụ về cách làm điều đó. 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() {

        }
    };

});

Về cơ bản, hãy gắn bộ điều khiển vào một chỉ thị đã xác định phạm vi cô lập. Phạm vi được đưa vào bộ điều khiển chỉ thị sẽ là phạm vi cô lập. Trong bộ điều khiển chỉ thị, bạn có thể đưa AlertFactory của mình vào mà bạn có thể chuyển phạm vi cô lập tới.


grrr..plnkr.co hiện đang ngoại tuyến. Hy vọng rằng liên kết vẫn hoạt động khi nó hoạt động trở lại.
rgaskill

Mmmm tôi nghĩ đó không phải là giải pháp tốt cho tôi, tôi không cần chỉ thị. Tôi cần có khả năng xuất xưởng để hiển thị hộp thoại cảnh báo phương thức. Vì vậy, tôi cần đính kèm html mẫu trong lớp phủ dom và sử dụng bộ điều khiển để quản lý dữ liệu trong chế độ xem cảnh báo.
Ngoại hạng

2
Tôi cho rằng bạn không nên điều khiển dom trong một nhà máy. Bạn đang trộn logic chế độ xem với logic kinh doanh của mình. Bạn có thể làm chính xác những gì bạn đã mô tả trong một chỉ thị nơi mà việc thao túng dom sẽ diễn ra.
rgaskill

Xem câu trả lời của Brad Green dành cho Andy về việc sử dụng dịch vụ cho một phương thức, thay vì một chỉ thị: blog.angularjs.org/2012/11/about-those-directives.html
Mark Rajcok

... Nhưng đối với trường hợp bootstrap cụ thể này, tôi nghĩ rằng nó được giải quyết tốt nhất bằng một chỉ thị. plnkr.co/edit/z4J8jH?p=preview
rgaskill Ngày
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.