অ্যাঙ্গুলারজেএস নিয়ন্ত্রণকারীদের বাড়ানোর প্রস্তাবিত উপায় কী?


193

আমার তিনটি নিয়ামক রয়েছে যা বেশ অনুরূপ। আমি একটি নিয়ামক রাখতে চাই যা এই তিনটি এর ক্রিয়াকলাপগুলি প্রসারিত এবং ভাগ করে।

উত্তর:


302

সম্ভবত আপনি কোনও নিয়ামক প্রসারিত করেন না তবে একটি নিয়ামক প্রসারিত করা বা একক নিয়ামককে একাধিক নিয়ামকের মিশ্রণ তৈরি করা সম্ভব।

module.controller('CtrlImplAdvanced', ['$scope', '$controller', function ($scope, $controller) {
    // Initialize the super class and extend it.
    angular.extend(this, $controller('CtrlImpl', {$scope: $scope}));
     Additional extensions to create a mixin.
}]);

যখন প্যারেন্ট কন্ট্রোলার তৈরি হয় তখন এর মধ্যে থাকা লজিকটিও কার্যকর হয়। আরও তথ্যের জন্য See নিয়ামক () দেখুন তবে কেবল $scopeমানটি পাস করতে হবে। অন্যান্য সমস্ত মানগুলি সাধারণত ইনজেকশন দেওয়া হবে।

@ মাওয়ারেন , আপনার উদ্বেগটি কৌণিক নির্ভরতা ইনজেকশন দ্বারা অটো- ম্যাজিকালি যত্ন নেওয়া হয়। আপনার কেবলমাত্র স্কোপ ইনজেকশন করা দরকার, যদিও আপনি চাইলে অন্যান্য ইনজেকশনের মানগুলি ওভাররাইড করতে পারেন। নিম্নলিখিত উদাহরণটি ধরুন:

(function(angular) {

	var module = angular.module('stackoverflow.example',[]);

	module.controller('simpleController', function($scope, $document) {
		this.getOrigin = function() {
			return $document[0].location.origin;
		};
	});

	module.controller('complexController', function($scope, $controller) {
		angular.extend(this, $controller('simpleController', {$scope: $scope}));
	});

})(angular);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>

<div ng-app="stackoverflow.example">
    <div ng-controller="complexController as C">
        <span><b>Origin from Controller:</b> {{C.getOrigin()}}</span>
    </div>
</div>

যদিও complex ডকুমেন্টটি 'কমপ্লেক্সকন্ট্রোলার' দ্বারা তৈরি করা হয় তখন সেটিকে 'সিম্পল কন্ট্রোলার'-এ প্রেরণ করা হয় না $ নথিটি আমাদের জন্য ইনজেকশনের পরে তৈরি করা হয়।


1
এর থেকে দ্রুততম, সবচেয়ে পরিষ্কার এবং সহজ সমাধান! ধন্যবাদ!
এমকে

নিখুঁত, দুর্দান্ত সমাধান!
কামিল Lach

8
আমার মনে হয় আপনার $.extend()$controller('CtrlImpl', {$scope: $scope});
এটির

5
@ টমরাইথেল ব্যবহার না করা angular.extend(বা $.extend) আসলে $scopeএকমাত্র প্রসারিত করার অর্থ , তবে যদি আপনার বেস কন্ট্রোলার কিছু বৈশিষ্ট্য (উদাহরণস্বরূপ this.myVar=5) ও সংজ্ঞায়িত করে থাকে তবে ব্যবহার করার সময় আপনার কেবলমাত্র this.myVarপ্রসারিত নিয়ন্ত্রকের অ্যাক্সেস থাকতে হবেangular.extend
স্কেলম্যাক্স

1
এটা অসাধারণ! সমস্ত প্রয়োজনীয় ক্রিয়াকলাপ প্রসারিত করার জন্য কেবল মনে রাখবেন, যেমন আমার কাছে এমন কিছু ছিল: handleSubmitClickযা ডাকে handleLoginযা পরিবর্তিতভাবে একটি loginSuccessএবং ছিল loginFail। সুতরাং, আমার বর্ধিত নিয়ামক মধ্যে আমি তখন জমিদার ছিল handleSubmitClick, handleLoginএবং loginSucessসঠিক জন্য loginSuccessফাংশন ব্যবহৃত হবে।
জাস্টিন ক্রুসে

52

উত্তরাধিকারের জন্য আপনি মানক জাভাস্ক্রিপ্ট উত্তরাধিকারের ধরণগুলি ব্যবহার করতে পারেন। এখানে একটি ডেমো যা ব্যবহার করে is$injector

function Parent($scope) {
  $scope.name = 'Human';
  $scope.clickParent = function() {
    $scope.name = 'Clicked from base controller';
  }    
}

function Child($scope, $injector) {
  $injector.invoke(Parent, this, {$scope: $scope});
  $scope.name = 'Human Child';
  $scope.clickChild = function(){
    $scope.clickParent();
  }       
}

Child.prototype = Object.create(Parent.prototype);

আপনি যদি controllerAsসিনট্যাক্সটি ব্যবহার করেন (যা আমি অত্যন্ত সুপারিশ করি) তবে শাস্ত্রীয় উত্তরাধিকারের ধরণটি ব্যবহার করা আরও সহজ:

function BaseCtrl() {
  this.name = 'foobar';
}
BaseCtrl.prototype.parentMethod = function () {
  //body
};

function ChildCtrl() {
  BaseCtrl.call(this);
  this.name = 'baz';
}
ChildCtrl.prototype = Object.create(BaseCtrl.prototype);
ChildCtrl.prototype.childMethod = function () {
  this.parentMethod();
  //body
};

app.controller('BaseCtrl', BaseCtrl);
app.controller('ChildCtrl', ChildCtrl);

আর একটি উপায় হতে পারে কেবল "বিমূর্ত" কনস্ট্রাক্টর ফাংশন তৈরি করা যা আপনার বেস নিয়ামক হবে:

function BaseController() {
  this.click = function () {
    //some actions here
  };
}

module.controller('ChildCtrl', ['$scope', function ($scope) {
  BaseController.call($scope);
  $scope.anotherClick = function () {
    //other actions
  };
}]);

এই বিষয়ে ব্লগ পোস্ট


16

ঠিক আছে, আপনি কী অর্জন করতে চান তা আমি নিশ্চিত নই, তবে সাধারণত পরিষেবাগুলিই যাওয়ার উপায়। আপনি কন্ট্রোলারের মধ্যে কোড ভাগ করতে কৌণিকের স্কোপের উত্তরাধিকার বৈশিষ্ট্যগুলিও ব্যবহার করতে পারেন:

<body ng-controller="ParentCtrl">
 <div ng-controller="FirstChildCtrl"></div>
 <div ng-controller="SecondChildCtrl"></div>
</body>

function ParentCtrl($scope) {
 $scope.fx = function() {
   alert("Hello World");
 });
}

function FirstChildCtrl($scope) {
  // $scope.fx() is available here
}

function SecondChildCtrl($scope) {
  // $scope.fx() is available here
}

একই রকম কাজ করে এমন নিয়ন্ত্রণকারীদের জুড়ে একই পরিবর্তনশীল এবং ফাংশনগুলি ভাগ করুন (একটি হ'ল সম্পাদনার জন্য, অন্যটি তৈরি করা ইত্যাদি ...)। এটি অবশ্যই সমাধানগুলির মধ্যে একটি ...
vladexologija

1
$ সুযোগ উত্তরাধিকার হ'ল এটি করার সর্বোত্তম উপায়, গৃহীত উত্তরের চেয়ে অনেক ভাল।
স্নেজ

শেষ পর্যন্ত এটি যেতে সবচেয়ে কৌণিক উপায় বলে মনে হয়েছিল। আমার কাছে তিনটি পৃথক পৃষ্ঠায় তিনটি সংক্ষিপ্ত প্যারেন্টকন্ট্রোলার রয়েছে যা কেবলমাত্র C স্কোপ মান নির্ধারণ করে যা চাইল্ডকন্ট্রোলার বেছে নিতে পারে। চাইল্ডকন্ট্রোলার, যা আমি প্রাথমিকভাবে প্রসারিত করার কথা ভেবেছিলাম, তাতে সমস্ত নিয়ামক যুক্তি রয়েছে।
mwarren

এটি করার পক্ষে $scope.$parent.fx( ) খুব পরিষ্কার উপায় হবে না, যেহেতু এটিই এখানে সংজ্ঞায়িত হয়েছে?
আকাশ

15

আপনি নিয়ন্ত্রকদের প্রসারিত করবেন না। যদি তারা একই বেসিক ফাংশন সম্পাদন করে তবে সেই ফাংশনগুলিকে একটি পরিষেবায় স্থানান্তরিত করা দরকার। এই পরিষেবাটি আপনার নিয়ামকদের মধ্যে ইনজেকশনের ব্যবস্থা করা যেতে পারে।


3
ধন্যবাদ, তবে আমার কাছে 4 টি ফাংশন রয়েছে যা ইতিমধ্যে পরিষেবাগুলি ব্যবহার করে (সংরক্ষণ করুন, মুছুন, ইত্যাদি ..) এবং তিনটি নিয়ামকের মধ্যে একই বিদ্যমান। যদি প্রসারিতকরণ কোনও বিকল্প না হয়, তবে কী 'মিক্সিন' হওয়ার সম্ভাবনা রয়েছে?
vladexologija

4
@vladexologija আমি বার্টের সাথে এখানে একমত। আমি মনে করি পরিষেবাগুলি মেশিনের। আপনার পক্ষে যুক্তিটি যতটা সম্ভব কন্ট্রোলারের বাইরে (পরিষেবাগুলিতে) সরিয়ে নেওয়ার চেষ্টা করা উচিত। সুতরাং যদি আপনার কাছে 3 টি নিয়ামক রয়েছে যা সাদৃশ্যপূর্ণ কাজগুলি করা দরকার তবে কোনও পরিষেবা গ্রহণের সঠিক পদ্ধতি বলে মনে হচ্ছে। কন্ট্রোলার প্রসারিত করা কৌণিকর মধ্যে প্রাকৃতিক বোধ করে না।
গণরাজ

6
@ ভ্লাডেক্সলোজিজিজা এখানে আমি কী বোঝাতে চাইছি তার একটি উদাহরণ এখানে দেওয়া হয়েছে: jsfiddle.net/ERGU3 এটি খুব মৌলিক তবে আপনি ধারণাটি পাবেন।
বার্ট

3
কোনও যুক্তি এবং আরও ব্যাখ্যা ছাড়াই উত্তরটি বেশ বেহুদা। আমিও মনে করি যে আপনি কিছুটা ওপি'র বক্তব্য মিস করেছেন। ইতিমধ্যে একটি ভাগ করা পরিষেবা রয়েছে। আপনি কেবলমাত্র সেই পরিষেবাটি সরাসরি প্রকাশ করা। আমি জানি না এটি ভাল ধারণা কিনা। সুযোগ অ্যাক্সেস প্রয়োজন হলে আপনার পদ্ধতির ব্যর্থতা। তবে আপনার যুক্তি অনুসরণ করে আমি স্পষ্টভাবে স্কোপটির সম্পত্তি হিসাবে দর্শন হিসাবে প্রকাশ করব যাতে এটি যুক্তি হিসাবে পাস করা যায় be
আরও ভাল অলিভার

6
একটি ক্লাসিক উদাহরণ হ'ল যখন আপনার সাইটে দুটি ফর্ম-চালিত প্রতিবেদন থাকবে, যার প্রত্যেকটি একই ডেটাতে প্রচুর পরিমাণে নির্ভর করে এবং যার প্রত্যেকটিতে প্রচুর অংশীদারি পরিষেবা ব্যবহার করা হয়। আপনি তাত্ত্বিকভাবে চেষ্টা করতে পারেন এবং কয়েকজন এজেএক্স কল সহ আপনার পৃথক পরিষেবাগুলিকে একটি বড় পরিষেবাতে স্থাপন করতে পারেন, এবং তারপরে 'getEverythingINeedForReport1' এবং 'getEverythingINeedForReport2' এর মতো পাবলিক পদ্ধতি থাকতে পারেন এবং সেগুলি একটি বিশাল স্কোপ অবজেক্টে সেট করে রেখেছেন তবে তারপরে আপনি আপনার পরিষেবায় যা নিয়মিত নিয়ন্ত্রক যুক্তিযুক্ত তা সত্যিই স্থাপন করা। প্রসারিত নিয়ন্ত্রকদের কিছু পরিস্থিতিতে একেবারে ব্যবহারের কেস রয়েছে।
tobylaroni

10

এই নিবন্ধ থেকে নেওয়া আরও একটি ভাল সমাধান :

// base controller containing common functions for add/edit controllers
module.controller('Diary.BaseAddEditController', function ($scope, SomeService) {
    $scope.diaryEntry = {};

    $scope.saveDiaryEntry = function () {
        SomeService.SaveDiaryEntry($scope.diaryEntry);
    };

    // add any other shared functionality here.
}])

module.controller('Diary.AddDiaryController', function ($scope, $controller) {
    // instantiate base controller
    $controller('Diary.BaseAddEditController', { $scope: $scope });
}])

module.controller('Diary.EditDiaryController', function ($scope, $routeParams, DiaryService, $controller) {
    // instantiate base controller
    $controller('Diary.BaseAddEditController', { $scope: $scope });

    DiaryService.GetDiaryEntry($routeParams.id).success(function (data) {
        $scope.diaryEntry = data;
    });
}]);

1
এটি আমার পক্ষে অত্যন্ত ভাল কাজ করেছে। আপনি এমন একটি পরিস্থিতি থেকে সহজ রিফ্যাক্টরিংয়ের সুবিধা পেয়েছেন যেখানে আপনি একজন নিয়ামক দিয়ে শুরু করেছিলেন, অন্য খুব অনুরূপ একটি তৈরি করেছেন এবং তারপরে কোডটি ডিওয়াইয়ার তৈরি করতে চেয়েছিলেন। আপনার কোডটি পরিবর্তন করার দরকার নেই, কেবল এটিকে টানুন এবং শেষ করুন।
এলি আলবার্ট

7

আপনি কোনও সার্ভিস তৈরি করতে পারেন এবং কেবল ইনজেকশনের মাধ্যমে কোনও নিয়ন্ত্রণকারীর মধ্যে এর আচরণের উত্তরাধিকারী হতে পারেন।

app.service("reusableCode", function() {

    var reusableCode = {};

    reusableCode.commonMethod = function() {
        alert('Hello, World!');
    };

    return reusableCode;
});

তারপরে আপনার নিয়ামকটিতে আপনি উপরের পুনঃব্যবহারযোগ্য কোড পরিষেবা থেকে প্রসারিত করতে চান:

app.controller('MainCtrl', function($scope, reusableCode) {

    angular.extend($scope, reusableCode);

    // now you can access all the properties of reusableCode in this $scope
    $scope.commonMethod()

});

ডেমো প্লানকার: http://plnkr.co/edit/EQtj6I0X08xprE8D0n5b?p= পূর্বরূপ


5

আপনি এরকম কিছু চেষ্টা করতে পারেন (পরীক্ষা করেননি):

function baseController(callback){
    return function($scope){
        $scope.baseMethod = function(){
            console.log('base method');
        }
        callback.apply(this, arguments);
    }
}

app.controller('childController', baseController(function(){

}));

1
হা. প্রসারিত করার জন্য কেবল প্রসারিত করার দরকার নেই
টেলরম্যাক

4

আপনি কোনও পরিষেবা , কারখানা বা সরবরাহকারী দিয়ে প্রসারিত করতে পারেন । তারা একই তবে নমনীয়তার বিভিন্ন ডিগ্রি সহ।

কারখানাটি ব্যবহার করে এখানে একটি উদাহরণ রয়েছে: http://jsfiddle.net/aaaflyvw/6KVtj/2/

angular.module('myApp',[])

.factory('myFactory', function() {
    var myFactory = {
        save: function () {
            // saving ...
        },
        store: function () {
            // storing ...
        }
    };
    return myFactory;
})

.controller('myController', function($scope, myFactory) {
    $scope.myFactory = myFactory;
    myFactory.save(); // here you can use the save function
});

এবং এখানে আপনি স্টোর ফাংশনটিও ব্যবহার করতে পারেন:

<div ng-controller="myController">
    <input ng-blur="myFactory.store()" />
</div>

4

আপনি সরাসরি $ নিয়ামক ('প্যারেন্টকন্ট্রোলার', {$ সুযোগ: $ সুযোগ}) উদাহরণ ব্যবহার করতে পারেন

module.controller('Parent', ['$scope', function ($scope) {
    //code
}])

module.controller('CtrlImplAdvanced', ['$scope', '$controller', function ($scope, $controller) {
    //extend parent controller
    $controller('CtrlImpl', {$scope: $scope});
}]);


1

আমি এটি করতে একটি ফাংশন লিখেছি:

function extendController(baseController, extension) {
    return [
        '$scope', '$injector',
        function($scope, $injector) {
            $injector.invoke(baseController, this, { $scope: $scope });
            $injector.invoke(extension, this, { $scope: $scope });
        }
    ]
}

আপনি এটি এর মতো ব্যবহার করতে পারেন:

function() {
    var BaseController = [
        '$scope', '$http', // etc.
        function($scope, $http, // etc.
            $scope.myFunction = function() {
                //
            }

            // etc.
        }
    ];

    app.controller('myController',
        extendController(BaseController,
            ['$scope', '$filter', // etc.
            function($scope, $filter /* etc. */)
                $scope.myOtherFunction = function() {
                    //
                }

                // etc.
            }]
        )
    );
}();

পেশাদাররা:

  1. আপনি বেস নিয়ামক নিবন্ধন করতে হবে না।
  2. কন্ট্রোলারের কারও কাছেই $ নিয়ামক বা ject ইনজেক্টর পরিষেবাদি সম্পর্কে জানা দরকার।
  3. এটি কৌণিকর অ্যারে ইনজেকশন সিনট্যাক্সের সাথে ভালভাবে কাজ করে - যা আপনার জাভাস্ক্রিপ্টটি খাটো করা হচ্ছে যদি প্রয়োজনীয়।
  4. আপনি সহজেই, বেস নিয়ামক অতিরিক্ত ইঞ্জেকশনভিত্তিক সেবা যোগ করতে পারেন ছাড়া তাদের যোগ করতে মনে রাখা হচ্ছে না, এবং, থেকে মাধ্যমে তাদের পাস আপনার সন্তানের কন্ট্রোলার সব।

কনস:

  1. বেস নিয়ামককে একটি পরিবর্তনশীল হিসাবে সংজ্ঞায়িত করতে হবে, যা বৈশ্বিক সুযোগকে দূষিত করার ঝুঁকিপূর্ণ। আমি বেনামে স্ব-কার্যকরকারী কার্যক্রমে সমস্ত কিছু মোড়ানো করে আমার ব্যবহারের উদাহরণে এড়ানো করেছি, তবে এর অর্থ এই নয় যে সমস্ত শিশু নিয়ন্ত্রককে একই ফাইলে ঘোষণা করতে হবে।
  2. আপনার এইচটিএমএল থেকে সরাসরি ইনস্ট্যান্ট করা নিয়ন্ত্রকদের পক্ষে এই প্যাটার্নটি ভাল কাজ করে তবে আপনি নিয়ন্ত্রণকারী () পরিষেবাটির মাধ্যমে আপনার কোড থেকে তৈরি করা নিয়ন্ত্রকদের পক্ষে এতটা ভাল নয়, কারণ এটি ইনজেক্টরের উপর নির্ভরতা আপনাকে সরাসরি অতিরিক্ত ইনজেকশন থেকে বাধা দেয়, অ আপনার কলিং কোড থেকে পরিষেবা পরামিতি।

1

আমি নিয়ন্ত্রণকারীদের প্রসারিতকে খারাপ অভ্যাস হিসাবে বিবেচনা করি। বরং আপনার ভাগ করা যুক্তি একটি পরিষেবাতে রাখুন। জাভাস্ক্রিপ্টে প্রসারিত অবজেক্টগুলি বরং জটিল হওয়ার প্রবণতা দেখায়। আপনি যদি উত্তরাধিকার ব্যবহার করতে চান তবে আমি টাইপস্ক্রিপ্টের পরামর্শ দেব। তবুও, আমার দৃষ্টিকোণে যাওয়ার জন্য পাতলা নিয়ন্ত্রণকারীরা আরও ভাল উপায়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.