2013-03-01 33 views
35

Tôi đang cố truy cập các thuộc tính của một chỉ thị trong hàm điều khiển. Tuy nhiên, vào thời điểm tôi truy cập nó, nó là không xác định. Tôi nhận thấy rằng nếu tôi làm một bộ đếm thời gian đơn giản nó hoạt động. Có cách nào để thực thi mã chỉ sau khi chỉ thị và phạm vi của nó đã sẵn sàng và được thiết lập để sử dụng không?AngularJS chỉ thị các thuộc tính truy cập từ bộ điều khiển

Tôi đã thực hiện điều đó. Đảm bảo bảng điều khiển của bạn đang mở. http://jsfiddle.net/paulocoelho/uKA2L/1/

Đây là mã tôi đang sử dụng trong fiddle:

<div ng-app="testApp" > 
    <testcomponent text="hello!"></testcomponent> 
</div> 
var module = angular.module('testApp', []) 
    .directive('testcomponent', function() { 
    return { 
     restrict: 'E', 
     template: '<div><p>{{text}} This will run fine! </p></div>', 
     scope: { 
      text: '@text' 
     }, 
     controller: function ($scope, $element) { 
      console.log($scope.text); // this will return undefined 
      setTimeout(function() { 
       console.log($scope.text); // this will return the actual value... 
      }, 1000); 
     }, 
     link: function ($scope, $element, $attrs) { 
      console.log($scope.text); 
      setTimeout(function() { 
       console.log($scope.text); 
      }, 1000); 
     } 
    }; 
}); 

Trả lời

25

Điều gì làm việc là, nếu bạn thiết lập

scope.text = $attrs.text; 

bên trong liên kết và các chức năng điều khiển. Điều này sẽ chỉ làm việc ban đầu, vì không có 2way- databinding. Bạn có thể sử dụng $attrs.observe.

Xem fiddle: http://jsfiddle.net/JohannesJo/nm3FL/2/

+0

yup, làm việc cho tôi :) nhờ người đàn ông – PCoelho

+1

này sẽ thất bại Linting. như 'attrs.text' không xác định. –

+1

@DougChamberlain Bạn có thể sử dụng JSDoc để đi xung quanh đó. Một cái gì đó như '' @param {string} attrs.text'' sẽ giải quyết vấn đề của bạn. –

1

Chức năng liên kết được gọi trước khi $ tiêu hóa vòng lặp, tại đó biến phạm vi thời điểm là không xác định. Hãy xem this chapterthis other để hiểu cách hoạt động của hàm liên kết. Bạn chỉ sử dụng chức năng liên kết để xác định đồng hồ và/hoặc hành vi cho chỉ thị, không thao tác với mô hình, điều này được thực hiện trong bộ điều khiển.

+0

Điều này không đúng. Phạm vi biến được xác định bởi thời gian chức năng post-link chạy, và nó là tốt để thao tác mô hình dữ liệu của bạn trong một chức năng liên kết. Bộ điều khiển chỉ cần thiết trên một chỉ thị nếu bạn dự định sử dụng nó để giao tiếp với một chỉ thị khác thông qua thuộc tính yêu cầu. Bộ điều khiển thực sự chạy đầu tiên, tiếp theo là các liên kết trước, đi tất cả các con đường xuống cây dom để lá, sau đó sau liên kết trở lại lên đến gốc. Tham khảo chủ đề này để làm rõ. https://stackoverflow.com/questions/24615103/angular-directives-when-and-how-to-use-compile-controller-pre-link-and-post –

23

Trong một phạm vi riêng biệt, không thể truy cập thuộc tính phạm vi cục bộ được xác định bằng '@' trong hàm liên kết. Như @remigio đã đề cập, các thuộc tính phạm vi địa phương như vậy là undefined tại thời điểm đó. $ attrs. $ observ() hoặc $ scope. $ watch() phải được sử dụng để lấy giá trị (interpolated) một cách không đồng bộ.

Nếu bạn đang chuyển giá trị không đổi trong thuộc tính, (nghĩa là không cần nội suy, nghĩa là giá trị của thuộc tính không chứa bất kỳ {{}} s) nào không cần '@' hoặc $ observer hoặc $ đồng hồ. Bạn có thể sử dụng $ attrs. attribute_name một lần như @hugo gợi ý, hoặc nếu bạn đang chuyển một số hoặc boolean và bạn muốn nhận được loại thích hợp, bạn có thể sử dụng $ scope. $ Eval ($ attrs. attribute_name) một lần.

Nếu bạn sử dụng '=' để databind thuộc tính phạm vi cục bộ thành thuộc tính phạm vi gốc, giá trị của thuộc tính sẽ có sẵn trong hàm liên kết (không cần $ quan sát hoặc $ watch hoặc $ eval).

+0

+1 Điều này khiến tôi phát điên. – GFoley83

+0

+1 Cảm ơn bạn đã giải thích! –

0

Nếu bạn đang truy cập giá trị này từ chỉ thị của bạn để chèn theo quan điểm của bạn sử dụng một chỉ thị, bạn có thể truy cập vào thuộc tính này bằng cách sử dụng api $ biên dịch và làm một cái gì đó như thế này

var string = "<div> " + scope.text + "</div>"; 
$compile(string)(scope, function(cloned, scope){ 
     element.append(cloned); 
}); 
7

Từ góc 1.3, bạn có thể sử dụng bindToController. Đây là một mẫu về cách tôi sử dụng nó. Ở đây, tôi thêm các thuộc tính để mô và sau đó sử dụng bindToController để sử dụng bên trong bộ điều khiển:

var module = angular.module('testApp', []) 
    .directive('testcomponent', function() { 
    return { 
     restrict: 'E', 
     template: '<div><p>{{text}} This will run fine! </p></div>', 
     scope: { 
      text: '@text' 
     }, 
     controller: function() { 
      console.log(this.text); 
     }, 
     controllerAs: 'vm', 
     bindToController: true 
    }; 
}); 

góc 1.3 ra mắt một tài sản mới để định nghĩa chỉ đối tượng gọi bindToController, mà thực hiện chính xác những gì nó nói. Khi đặt thành true theo chỉ thị với phạm vi phân lập sử dụng controllerAs, các thuộc tính của thành phần được ràng buộc với bộ điều khiển chứ không phải là phạm vi.Điều đó có nghĩa là, Angular đảm bảo rằng, khi bộ điều khiển là được khởi tạo, các giá trị ban đầu của các kết buộc phạm vi bị cô lập là khả dụng trên này và các thay đổi trong tương lai cũng tự động có sẵn .

+1

Điều này không hiệu quả đối với tôi, this.text không được xác định. – rjh

+0

@rjh Bạn đã chuyển 'văn bản' khi gọi chỉ thị như thế này chưa? '' – Neel

5

Thay vì sử dụng $scope để có được chỉ thị thuộc tính giá trị, cá nhân tôi thích sử dụng $attrs cho controller chức năng, hoặc chỉ attrs ở tham số thứ 3 của link chức năng. Tôi không có vấn đề khi nhận được giá trị thuộc tính từ một controller bằng cách làm theo mã mà không thời gian chờ:

var module = angular.module('testApp', []) 
    .directive('testcomponent', function() { 
    return { 
    restrict: 'E', 
    template: '<div><p>{{text}} This will run fine! </p></div>', 
    scope: { 
     text: '@text' 
    }, 
    controller: ['$scope','$attrs', function ($scope, $attrs) { 
     console.log($attrs.text); // just call to the $attrs instead $scope and i got the actual value 
     $scope.text = $attrs.text; //assign attribute to the scope 
    }] 
    }; 
}); 
Các vấn đề liên quan