Bisakah saya membuat fungsi tersedia di setiap pengontrol di sudut?

191

Jika saya memiliki fungsi utilitas fooyang saya ingin dapat menelepon dari mana saja di dalam ng-appdeklarasi saya . Apakah ada cara saya dapat membuatnya dapat diakses secara global dalam pengaturan modul saya atau apakah saya perlu menambahkannya ke ruang lingkup di setiap pengontrol?

Ludwig Magnusson
sumber
Saya tidak 100% yakin tentang ini, tetapi ada kemungkinan Anda juga dapat mendefinisikannya pada modul Anda seperti ini: module.value('myFunc', function(a){return a;});dan kemudian menyuntikkannya dengan nama di controller Anda. (Jika seseorang ingin menghindari membuat layanan)
user2173353
Artinya saya harus menambahkannya ke setiap pengontrol secara manual. $ rootScope adalah cara untuk melakukan apa yang ingin saya lakukan hampir 2 tahun yang lalu =)
Ludwig Magnusson
BAIK. :) Saya hanya menggunakan arahan dengan lingkup terisolasi lebih sering daripada pengontrol biasa dan saya harus menyuntikkan semuanya. Saya suka gaya kode modular yang disediakan ini. Selain itu, Anda tidak perlu mengacaukan cakupan induk dengan cara apa pun dan Anda tidak perlu mencari banyak dari mana variabel lingkup Anda berasal. :)
user2173353

Jawaban:

290

Pada dasarnya Anda memiliki dua opsi, baik mendefinisikannya sebagai layanan, atau menempatkannya pada ruang lingkup root Anda. Saya menyarankan agar Anda membuat layanan untuk menghindari polusi pada ruang lingkup root. Anda membuat layanan dan membuatnya tersedia di controller Anda seperti ini:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.factory('myService', function() {
        return {
            foo: function() {
                alert("I'm foo!");
            }
        };
    });

    myApp.controller('MainCtrl', ['$scope', 'myService', function($scope, myService) {
        $scope.callFoo = function() {
            myService.foo();
        }
    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="callFoo()">Call foo</button>
</body>
</html>

Jika itu bukan opsi untuk Anda, Anda dapat menambahkannya ke cakupan root seperti ini:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.run(function($rootScope) {
        $rootScope.globalFoo = function() {
            alert("I'm global foo!");
        };
    });

    myApp.controller('MainCtrl', ['$scope', function($scope){

    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="globalFoo()">Call global foo</button>
</body>
</html>

Dengan begitu, semua templat Anda dapat memanggil globalFoo()tanpa harus meneruskannya ke templat dari controller.

Anders Ekdahl
sumber
5
Dalam solusi pertama, bagaimana jika ada banyak foo()fungsi? Membuat $scope.callFoo()pembungkus untuk masing-masing adalah terlalu banyak pekerjaan. Bagaimana saya bisa "melampirkan" semua fungsi perpustakaan ke dalam ruang lingkup sehingga dapat digunakan dalam templat? Saya memiliki perpustakaan konversi unit besar yang saya inginkan tersedia di template saya.
AlexStack
3
Pertanyaan saya juga. Saya mencoba ini dan berhasil: Anda dapat "melampirkan" dengan mengatakan $scope.callFoo = myService.foo;di tempat membuat pembungkus baru di setiap tempat yang ingin Anda gunakan.
Fitter Man
1
Terima kasih atas bantuan Anda, saya ingin tahu bagaimana menyediakan fungsi perubahan bahasa di seluruh aplikasi saya dan $ rootScope melakukan pekerjaannya. Saya ingin memisahkan modul terjemahan dari aplikasi sehingga saya dapat menyambungkannya ke aplikasi lain juga.
Paulo Pedroso
Saya sarankan menggunakan Nilai Sudut daripada Pabrik untuk kasus khusus ini kecuali jika Anda berencana memiliki beberapa fungsi dalam layanan. Jika hanya satu fungsi, jadikan itu Nilai.
Nicholas Blasgen
Saya mendapat Kesalahan: [$ injector: uns]
Mark Thien
53

Anda juga dapat menggabungkannya, saya kira:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
        var myApp = angular.module('myApp', []);

        myApp.factory('myService', function() {
            return {
                foo: function() {
                    alert("I'm foo!");
                }
            };
        });

        myApp.run(function($rootScope, myService) {
            $rootScope.appData = myService;
        });

        myApp.controller('MainCtrl', ['$scope', function($scope){

        }]);

    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="appData.foo()">Call foo</button>
</body>
</html>
Ric
sumber
7
Saya pikir ini harus jawaban yang benar, dibenarkan oleh jawaban @Praym. Tidak masuk akal menentukan ketergantungan layanan di 10 pengontrol yang berbeda.
jvannistelrooy
Bisakah layanan mencakup metode / fungsi yang dapat properti / variabel CRUD di $rootScope?
jezmck
44

Meskipun pendekatan pertama dianjurkan sebagai pendekatan 'sudut', saya merasa ini menambah biaya tambahan.

Pertimbangkan jika saya ingin menggunakan fungsi myservice.foo ini di 10 pengontrol yang berbeda. Saya harus menentukan dependensi 'myService' ini dan kemudian properti scope $ scope.callFoo di dalam semuanya. Ini hanyalah pengulangan dan entah bagaimana melanggar prinsip KERING.

Sedangkan, jika saya menggunakan pendekatan $ rootScope, saya menetapkan fungsi global ini hanya satu kali dan global akan tersedia di semua pengontrol masa depan saya, tidak peduli berapa banyak.

Praym
sumber
5
Mungkin ada beberapa nilai dalam 'dokumentasi' pengendali tempat mereka mendapatkan panggilan layanan global tersebut. Jika Anda adalah Anda menarik salah satu pengendali Anda ke aplikasi lain itu akan kurang jelas dari mana fungsi global itu berasal. Saya mendengar mengenali argumen Anda.
Matthew Payne
Itu hanya harus diletakkan pada ruang lingkup jika Anda perlu menyebutnya dari tampilan. Di controller, Anda dapat memanggilnya langsung dari layanan.
mcv
10
Ini adalah komentar, bukan jawaban
Elliott
Variabel $ rootScope selalu null pada refresh halaman dalam hal ini Anda tidak akan mendapatkan fungsinya. Itu sebabnya bagus untuk menyuntikkan layanan dan menggunakan referensi dalam aplikasi.
Ehsan Hafeez
4

AngularJs memiliki " Layanan " dan " Pabrik " hanya untuk masalah seperti milik Anda. Ini digunakan untuk memiliki sesuatu yang global antara Pengontrol, Arahan, Layanan Lain atau komponen angular lainnya .. Anda dapat menentukan fungsi, menyimpan data, membuat fungsi penghitungan, atau apa pun yang Anda ingin di dalam Layanan dan menggunakannya dalam AngularJs Components sebagai Global .like

angular.module('MyModule', [...])
  .service('MyService', ['$http', function($http){
    return {
       users: [...],
       getUserFriends: function(userId){
          return $http({
            method: 'GET',
            url: '/api/user/friends/' + userId
          });
       }
       ....
    }
  }])

jika Anda membutuhkan lebih banyak

Temukan Lebih Banyak Tentang Mengapa Kami Membutuhkan Layanan dan Pabrik Angular

Hazarapet Tunanyan
sumber
0

Saya sedikit lebih baru untuk Angular tetapi apa yang saya temukan berguna untuk dilakukan (dan cukup sederhana) adalah saya membuat skrip global yang saya muat ke halaman saya sebelum skrip lokal dengan variabel global yang perlu saya akses di semua halaman. Dalam skrip itu, saya membuat objek yang disebut "globalFunctions" dan menambahkan fungsi yang saya perlu akses secara global sebagai properti. mis globalFunctions.foo = myFunc();. Kemudian, di setiap skrip lokal, saya menulis $scope.globalFunctions = globalFunctions;dan saya langsung memiliki akses ke fungsi apa pun yang saya tambahkan ke objek globalFunctions dalam skrip global.

Ini sedikit solusi dan saya tidak yakin itu membantu Anda, tetapi itu pasti membantu saya karena saya memiliki banyak fungsi dan itu menyakitkan menambahkan semuanya ke setiap halaman.

Izzy
sumber
1
Saya hanya ingin tahu mengapa downvotes? Saya baru dan ingin tahu dari pro.
Izzy
Sepertinya solusi yang berfungsi untuk saya. Satu-satunya hal yang saya sarankan, untuk memastikan ruang lingkup Anda cukup terisolasi, adalah untuk membuat kelas utilitas Javascript root global dan menggantung metode utilitas Anda sehingga Anda tidak sengaja menginjak beberapa nama fungsi lain di lautan luas benda yang disuntikkan oleh Angular.
JE Carter II
Satu hal yang perlu diperhatikan, dan mungkin mengapa hal ini dibatalkan, Anda hanya dapat menggunakan fungsi-fungsi itu di template Anda, bukan modul .ts Anda karena panggilan fungsi Anda tidak akan diselesaikan pada waktu kompilasi. Inilah alasan untuk melakukannya dengan cara "bersudut". Tetapi, jika Anda hanya ingin menambahkan dekorator dan semacamnya ke template Anda, file utilitas global sederhana dan baik.
JE Carter II