Phạm vi truy cập AngularJS từ bên ngoài chức năng js


131

Tôi đang cố gắng xem liệu có một cách đơn giản để truy cập phạm vi bên trong của bộ điều khiển thông qua chức năng javascript bên ngoài (hoàn toàn không liên quan đến bộ điều khiển đích)

Tôi đã thấy một vài câu hỏi khác ở đây rằng

angular.element("#scope").scope();

sẽ lấy lại phạm vi từ một phần tử DOM, nhưng những nỗ lực của tôi hiện không mang lại kết quả chính xác nào.

Đây là jsfiddle: http://jsfiddle.net/sXkjc/5/

Tôi hiện đang trải qua quá trình chuyển đổi từ JS đơn giản sang Angular. Lý do chính tôi đang cố gắng để đạt được điều này là để giữ cho mã thư viện ban đầu của tôi nguyên vẹn nhất có thể; tiết kiệm nhu cầu cho tôi để thêm từng chức năng vào bộ điều khiển.

Có ý tưởng nào về cách tôi có thể đạt được điều này không? Nhận xét về các fiddle trên cũng được chào đón.


FYI theo các tài liệu sử dụng .scope()yêu cầu phải bật Dữ liệu gỡ lỗi nhưng sử dụng Dữ liệu gỡ lỗi trong sản xuất không được khuyến nghị vì lý do tốc độ. Các giải pháp dưới đây dường như xoay quanhscope()
rtpHarry

@rtpHarry nói đúng. Câu trả lời dưới đây yêu cầu sử dụng scope () không được dùng nữa. Xem câu trả lời của tôi ở đây stackoverflow.com/a/34078750/319302
Cagatay Kalan

Câu trả lời:


223

Bạn cần sử dụng $ scope. $ Apply () nếu bạn muốn thực hiện bất kỳ thay đổi nào đối với giá trị phạm vi từ bên ngoài sự kiểm soát của angularjs như trình xử lý sự kiện jquery / javascript.

function change() {
    alert("a");
    var scope = angular.element($("#outer")).scope();
    scope.$apply(function(){
        scope.msg = 'Superhero';
    })
}

Demo: Fiddle


2
@ dk123 angular.element("#scope")không hoạt động, mặc dù angular.element($("#scope"))đang hoạt động, bạn cũng cần phải có jquery
Arun P Johny

1
Tôi biết đã được một lúc, nhưng tôi hy vọng một số người có thể trả lời tôi về điều này ... Tại sao var scope = angular.element ($ ("# ngoài")). Range (); Có phải khai báo bên trong hàm thay đổi? Nếu tôi di chuyển nó vào không gian toàn cầu thì không phải sao?
Marc M.

1
@MarcM. Tôi nghĩ rằng nó có liên quan đến giải trí phạm vi của Angular. Vào thời điểm bạn đang sử dụng chức năng thay đổi, phạm vi trước đó var toàn cầu đã trỏ đến có thể không còn tồn tại (do giải trí).
dk123

1
angular.element ($ ("div [ng-control = 'myCtrl']")). scope (); tốt hơn so với #outer bổ sung trong phần tử div, tôi đoán
wyverny

1
scope () không được xác định khi chúng ta làm: $ compileProvider.debugInfoEnabled (false); trong góc cạnh. Vậy làm thế nào chúng ta có thể làm cho nó hoạt động với debuginfoEnables false?
Agnosco

26

Đã được một thời gian kể từ khi tôi đăng câu hỏi này, nhưng xem xét các quan điểm mà dường như vẫn nhận được, đây là một giải pháp khác mà tôi đã đưa ra trong vài tháng qua:

$scope.safeApply = function( fn ) {
    var phase = this.$root.$$phase;
    if(phase == '$apply' || phase == '$digest') {
        if(fn) {
            fn();
        }
    } else {
        this.$apply(fn);
    }
};

Đoạn mã trên về cơ bản tạo ra một chức năng gọi safeApplylà Calles các $applychức năng (như đã nêu trong câu trả lời của Arun) khi và chỉ kiễu góc hiện không được trải qua các $digestgiai đoạn. Mặt khác, nếu Angular hiện đang tiêu hóa mọi thứ, nó sẽ chỉ thực thi chức năng như vậy, vì điều đó sẽ đủ để báo hiệu cho Angular thực hiện các thay đổi.

Vô số lỗi xảy ra khi cố gắng sử dụng $applychức năng trong khi AngularJs hiện đang ở $digestgiai đoạn của nó . Các safeApplymã trên là một wrapper an toàn để ngăn chặn các lỗi như vậy.

(lưu ý: Cá nhân tôi thích tặc lưỡi safeApplynhư một chức năng $rootScopecho mục đích thuận tiện)

Thí dụ:

function change() {
    alert("a");
    var scope = angular.element($("#outer")).scope();
    scope.safeApply(function(){
        scope.msg = 'Superhero';
    })
}

Bản trình diễn: http://jsfiddle.net/sXkjc/227/


1
Tại sao chức năng safeApply của bạn hoạt động? Có vẻ như những gì bạn đang nói là "tự thực thi chức năng nếu Angular ở trong giai đoạn $ áp dụng hoặc $ digest, nếu không thì sử dụng $ áp dụng () để áp dụng chức năng" .... Nhưng nếu bạn tự thực hiện chức năng đó .. .. làm thế nào để cập nhật bất kỳ mô hình? Có vẻ như đó sẽ không phải là hành vi thuận lợi, trừ khi có điều gì đó xảy ra mà tôi không biết. Có một số cơ chế trong Angular đi thăm dò phạm vi $ cho những thay đổi có thể xảy ra trực tiếp với nó không ???
trusktr

Ngoài ra, nếu bạn cần bảo vệ chống lại các trạng thái đó, thì tôi sẽ xem xét rằng lỗi của phương thức $ áp dụng () cần được sửa chữa.
trusktr

@trusktr Theo những gì tôi hiểu, việc thực hiện chức năng thông thường sẽ bị bắt bởi góc nếu chức năng thay đổi bất kỳ mô hình nào, và do đó góc cập nhật chúng trong giai đoạn tiêu hóa tiếp theo.
dk123

@trusktr Tôi đồng ý rằng nếu $ áp dụng () bình thường có thể được áp dụng mà không có biện pháp bảo vệ, sẽ không có gì tốt hơn. Về bản chất, mục đích duy nhất của safeApply là bảo vệ chống lại các lỗi $ áp dụng (). Không chắc chắn nếu đây là một vấn đề được báo cáo và hiện đã được khắc phục, hoặc vẫn còn là một vấn đề đang diễn ra.
dk123

1
Chỉ vì tôi vấp phải nó: github.com/angular/angular.js/wiki/When-to-use-$scope.$apply () . _Nếu bạn đang thực hiện nếu (! $ Phạm vi. $$ pha) $ phạm vi. $ Áp dụng () đó là vì bạn không đủ cao trong ngăn xếp cuộc gọi._
scheffield

17

Một cách khác để làm điều đó là:

var extScope;
var app = angular.module('myApp', []);
app.controller('myController',function($scope, $http){
    extScope = $scope;
})
//below you do what you want to do with $scope as extScope
extScope.$apply(function(){
    extScope.test = 'Hello world';
})

1
Tôi vẫn không hiểu tại sao bình luận này không phải là câu trả lời tốt nhất cho điều này. Sau khi đào internet được vài ngày, với sự thất vọng và tức giận, cuối cùng đây là điều đã giải quyết vấn đề của tôi. Cảm ơn bạn @Charleston. Bạn thật tuyệt vời, thưa ngài!
Rajkumar

13

chúng ta có thể gọi nó sau khi tải

http://jsfiddle.net/gentletech/s3qtv/3/

<div id="wrap" ng-controller="Ctrl">
    {{message}}<br>
    {{info}}
    </div>
    <a  onClick="hi()">click me </a>

    function Ctrl($scope) {
        $scope.message = "hi robi";
        $scope.updateMessage = function(_s){
            $scope.message = _s;    
        };
    }

function hi(){
    var scope = angular.element(document.getElementById("wrap")).scope();
        scope.$apply(function() {
        scope.info = "nami";
        scope.updateMessage("i am new fans like nami");
    });
}

8

Đã lâu rồi tôi mới hỏi câu hỏi này, nhưng đây là một câu trả lời không đòi hỏi phải có sự châm biếm:

function change() {
    var scope = angular.element(document.querySelector('#outside')).scope();
    scope.$apply(function(){
        scope.msg = 'Superhero';
    })
}

3

Đây là một giải pháp có thể sử dụng lại: http://jsfiddle.net/flobar/r28b0gmq/

function accessScope(node, func) {
    var scope = angular.element(document.querySelector(node)).scope();
    scope.$apply(func);
}

window.onload = function () {

    accessScope('#outer', function (scope) {
        // change any property inside the scope
        scope.name = 'John';
        scope.sname = 'Doe';
        scope.msg = 'Superhero';
    });

};

2

Bạn cũng có thể thử:

function change() {
    var scope = angular.element( document.getElementById('outer') ).scope();
    scope.$apply(function(){
        scope.msg = 'Superhero';
    })
}

@ dk123 đây cũng không cần liều JQuery.
harish sharma

1

Câu trả lời được chấp nhận là rất tốt. Tôi muốn xem xét những gì xảy ra với phạm vi Angular trong bối cảnh ng-repeat. Vấn đề là, Angular sẽ tạo ra một phạm vi phụ cho mỗi mục lặp lại. Khi gọi vào một phương thức được xác định trên bản gốc $scope, nó vẫn giữ nguyên giá trị ban đầu của nó (do đóng javascript). Tuy nhiên, thisđề cập đến phạm vi / đối tượng gọi. Điều này hoạt động tốt, miễn là bạn rõ ràng khi nào $scopethisgiống nhau và khi chúng khác nhau. thứ

Đây là một câu đố minh họa cho sự khác biệt: https://jsfiddle.net/creitzel/oxsxjcyc/


1

Tôi là người mới, rất xin lỗi nếu là một thực hành xấu. Dựa trên câu trả lời đã chọn, tôi đã thực hiện chức năng này:

function x_apply(selector, variable, value) {
    var scope = angular.element( $(selector) ).scope();
    scope.$apply(function(){
        scope[variable] = value;
    });
}

Tôi đang sử dụng nó theo cách này:

x_apply('#fileuploader', 'thereisfiles', true);

Nhân tiện, xin lỗi vì tiếng anh của tôi


0
<input type="text" class="form-control timepicker2" ng-model='programRow.StationAuxiliaryTime.ST88' />

truy cập giá trị phạm vi

giả sử rằng chương trìnhRow.StationAuxadderTime là một mảng của đối tượng

 $('.timepicker2').on('click', function () 
    {
            var currentElement = $(this);

            var scopeValues = angular.element(currentElement).scope();
            var model = currentElement.attr('ng-model');
            var stationNumber = model.split('.')[2];
            var val = '';
            if (model.indexOf("StationWaterTime") > 0) {
                val = scopeValues.programRow.StationWaterTime[stationNumber];
            }
            else {
                val = scopeValues.programRow.StationAuxiliaryTime[stationNumber];
            }
            currentElement.timepicker('setTime', val);
        });

0

Chúng ta cần sử dụng Angular Js được xây dựng trong hàm $ áp dụng cho các biến phạm vi hoặc các hàm phạm vi bên ngoài hàm điều khiển.

Điều này có thể được thực hiện theo hai cách :

| * | Phương pháp 1: Sử dụng Id:

<div id="nameNgsDivUid" ng-app="">
    <a onclick="actNgsFnc()"> Activate Angular Scope</a><br><br>
    {{ nameNgsVar }}
</div>

<script type="text/javascript">

    var nameNgsDivVar = document.getElementById('nameNgsDivUid')

    function actNgsFnc()
    {
        var scopeNgsVar = angular.element(nameNgsDivVar).scope();
        scopeNgsVar.$apply(function()
        {
            scopeNgsVar.nameNgsVar = "Tst Txt";
        })
    }

</script>

| * | Cách 2: Sử dụng init của ng-controller:

<div ng-app="nameNgsApp" ng-controller="nameNgsCtl">
    <a onclick="actNgsFnc()"> Activate Angular Scope</a><br><br>
    {{ nameNgsVar }}
</div>

<script type="text/javascript">

    var scopeNgsVar;
    var nameNgsAppVar=angular.module("nameNgsApp",[])
    nameNgsAppVar.controller("nameNgsCtl",function($scope)
    {
        scopeNgsVar=$scope;
    })

    function actNgsFnc()
    {
        scopeNgsVar.$apply(function()
        {
            scopeNgsVar.nameNgsVar = "Tst Txt";
        })
    }

</script>
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.