Bagaimana cara membutuhkan pengontrol dalam direktif angularjs

86

Adakah yang bisa memberi tahu saya cara menyertakan pengontrol dari satu direktif di direktif angularJS lain. misalnya saya memiliki kode berikut

var app = angular.module('shop', []).
config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/', {
        templateUrl: '/js/partials/home.html'
    })
        .when('/products', {
        controller: 'ProductsController',
        templateUrl: '/js/partials/products.html'
    })
        .when('/products/:productId', {
        controller: 'ProductController',
        templateUrl: '/js/partials/product.html'
    });
}]);

app.directive('mainCtrl', function () {
    return {
        controller: function ($scope) {}
    };
});

app.directive('addProduct', function () {
    return {
        restrict: 'C',
        require: '^mainCtrl',
        link: function (scope, lElement, attrs, mainCtrl) {
            //console.log(cartController);
        }
    };
});

Dengan semua akun, saya seharusnya dapat mengakses pengontrol di arahan addProduct tetapi saya tidak. Apakah ada cara yang lebih baik untuk melakukan ini?

Le Garden Fox
sumber
5
requirememastikan adanya direktif lain dan kemudian menyertakan pengontrolnya. ^requirememeriksa elemen di atas elemen saat ini selain elemen saat ini. Jadi, Anda harus menggunakan kedua arahan bersama agar ini berhasil. Jika tidak, cukup tentukan pengontrol dengan app.controllerlalu gunakan di kedua arahan. Apa pun itu, dapatkah Anda memasukkan ini ke dalam Plunker sederhana bersama dengan kode HTML Anda?
Josh David Miller

Jawaban:

187

Saya beruntung dan menjawab ini dengan mengomentari pertanyaan, tetapi saya memposting jawaban lengkap demi kelengkapan sehingga kami dapat menandai pertanyaan ini sebagai "Dijawab".


Itu tergantung pada apa yang ingin Anda capai dengan berbagi pengontrol; Anda dapat berbagi pengontrol yang sama (meskipun memiliki contoh yang berbeda), atau Anda dapat berbagi contoh pengontrol yang sama.

Bagikan Pengontrol

Dua arahan dapat menggunakan pengontrol yang sama dengan meneruskan metode yang sama ke dua arahan, seperti:

app.controller( 'MyCtrl', function ( $scope ) {
  // do stuff...
});

app.directive( 'directiveOne', function () {
  return {
    controller: 'MyCtrl'
  };
});

app.directive( 'directiveTwo', function () {
  return {
    controller: 'MyCtrl'
  };
});

Setiap direktif akan mendapatkan contoh pengontrolnya sendiri, tetapi ini memungkinkan Anda untuk berbagi logika di antara sebanyak mungkin komponen yang Anda inginkan.

Membutuhkan Pengontrol

Jika Anda ingin berbagi contoh pengontrol yang sama, gunakan require.

requirememastikan keberadaan direktif lain dan kemudian menyertakan pengontrolnya sebagai parameter ke fungsi tautan. Jadi, jika Anda memiliki dua arahan pada satu elemen, arahan Anda dapat memerlukan keberadaan arahan lain dan mendapatkan akses ke metode pengontrolnya. Kasus penggunaan umum untuk ini adalah mensyaratkan ngModel.

^require, dengan tambahan tanda sisipan, periksa elemen direktif di atas selain elemen saat ini untuk mencoba menemukan direktif lainnya. Hal ini memungkinkan Anda untuk membuat komponen kompleks di mana "sub-komponen" dapat berkomunikasi dengan komponen induk melalui pengontrolnya untuk mendapatkan efek yang hebat. Contohnya dapat mencakup tab, di mana setiap panel dapat berkomunikasi dengan keseluruhan tab untuk menangani pengalihan; satu set akordeon dapat memastikan hanya satu yang terbuka pada satu waktu; dll.

Di kedua acara, Anda harus menggunakan kedua arahan bersama agar ini bekerja. requireadalah cara berkomunikasi antar komponen.

Lihat halaman Panduan tentang arahan untuk info lebih lanjut: http://docs.angularjs.org/guide/directive

Josh David Miller
sumber
4
Apakah mungkin memerlukan pengontrol direktif saudara kandung? Pada dasarnya saya perlu berbagi contoh yang sama dari pengontrol atau layanan antara arahan saudara (seperti pada saudara DOM, bukan pada elemen DOM yang sama) yang diulang menggunakan ng-repeat. Bayangkan setiap item yang berulang memiliki arahan yang membutuhkan keadaan atau logika bersama di antara mereka.
CMCDragonkai
2
@CMCDragonkai Tidak ada cara untuk melakukan itu, tetapi ada dua cara umum untuk mencapai hal yang sama. Yang pertama adalah jika saudara kandung semuanya memiliki "tipe" yang sama maka elemen di atas ngRepeat bisa seperti direktif penampung dan semua sub-elemen kemudian dapat meminta direktif tersebut, semua berbagi pengontrol yang sama. Solusi yang lebih umum - dan seringkali lebih kanonik - adalah menggunakan layanan bersama. Bisakah Anda menjelaskan apa yang dilakukan saudara-saudara ini dan apa yang perlu mereka bagikan?
Josh David Miller
Ya akhirnya melakukan opsi pertama. Menggunakan pengontrol direktif kontainer. Bekerja dengan baik. Ini untuk Masonry.
CMCDragonkai
Ini adalah jawaban yang bagus dan telah memperkuat pemahaman saya tentang bagaimana semua ini bekerja. Terima kasih! (Sebagai catatan, ini mungkin fitur yang lebih baru, tetapi Anda dapat menggunakan requireuntuk menentukan satu direktif, atau serangkaian arahan; setiap arahan dapat diawali dengan tanda sisipan ( ^) untuk persyaratan yang lebih terperinci.)
jedd.ahyoung
Menggunakan pengontrol yang sama dalam dua arahan tidak memberikan setiap direktif itu sendiri contohnya.
jsbisht
27

Ada jawaban stackoverflow yang bagus di sini oleh Mark Rajcok:

Pengontrol direktif AngularJS membutuhkan pengontrol direktif orang tua?

dengan tautan ke jsFiddle yang sangat jelas ini: http://jsfiddle.net/mrajcok/StXFK/

<div ng-controller="MyCtrl">
    <div screen>
        <div component>
            <div widget>
                <button ng-click="widgetIt()">Woo Hoo</button>
            </div>
        </div>
    </div>
</div>

JavaScript

var myApp = angular.module('myApp',[])

.directive('screen', function() {
    return {
        scope: true,
        controller: function() {
            this.doSomethingScreeny = function() {
                alert("screeny!");
            }
        }
    }
})

.directive('component', function() {
    return {
        scope: true,
        require: '^screen',
        controller: function($scope) {
            this.componentFunction = function() {
                $scope.screenCtrl.doSomethingScreeny();
            }
        },
        link: function(scope, element, attrs, screenCtrl) {
            scope.screenCtrl = screenCtrl
        }
    }
})

.directive('widget', function() {
    return {
        scope: true,
        require: "^component",
        link: function(scope, element, attrs, componentCtrl) {
            scope.widgetIt = function() {
                componentCtrl.componentFunction();
            };
        }
    }
})


//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});

function MyCtrl($scope) {
    $scope.name = 'Superhero';
}
Joseph Oster
sumber
4
Bagi saya, yang membuat contoh Mark Rajcok paling banyak diklik adalah memperhatikan bagaimana metode pengontrol dibuat. Biasanya Anda melihat metode pengontrol yang dibuat melalui $ scope.methodName = function () {...}, tetapi agar ini berfungsi, Anda harus menggunakan this.methodName untuk metode yang ingin Anda akses. Saya tidak menyadarinya pada awalnya.
coblr