AngularJS 컨트롤러를 확장하는 데 권장되는 방법은 무엇입니까?
꽤 비슷한 세 개의 컨트롤러가 있습니다. 이 세 가지 기능을 확장하고 공유하는 컨트롤러를 갖고 싶습니다.
아마도 당신은 컨트롤러를 확장하지 않습니다하지만 컨트롤러를 확장하거나 하나의 컨트롤러를 여러 컨트롤러의 믹스 인을 만드는 것이 가능하다.
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.
}]);
상위 컨트롤러가 생성되면 그 안에 포함 된 로직도 실행됩니다. $scope
값만 전달 하면되지만 자세한 내용은 $ controller ()를 참조하십시오 . 다른 모든 값은 정상적으로 주입됩니다.
@mwarren , Angular 의존성 주입으로 문제를 자동으로 처리합니다. 필요한 경우 $ 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>
'complexController'에 의해 생성 될 때 $ document가 'simpleController'에 전달되지 않지만 $ document가 우리에게 주입됩니다.
상속을 위해 표준 JavaScript 상속 패턴을 사용할 수 있습니다. 다음은 사용하는 데모입니다$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
};
}]);
글쎄, 나는 당신이 무엇을 달성하고자하는지 확실하지 않지만 일반적으로 서비스가 갈 길입니다. Angular의 Scope 상속 특성을 사용하여 컨트롤러간에 코드를 공유 할 수도 있습니다.
<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
}
You don't extend controllers. If they perform the same basic functions then those functions need to be moved to a service. That service can be injected into your controllers.
Yet another good solution taken from this article:
// 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;
});
}]);
You can create a service and inherit its behaviour in any controller just by injecting it.
app.service("reusableCode", function() {
var reusableCode = {};
reusableCode.commonMethod = function() {
alert('Hello, World!');
};
return reusableCode;
});
Then in your controller that you want to extend from the above reusableCode service:
app.controller('MainCtrl', function($scope, reusableCode) {
angular.extend($scope, reusableCode);
// now you can access all the properties of reusableCode in this $scope
$scope.commonMethod()
});
DEMO PLUNKER: http://plnkr.co/edit/EQtj6I0X08xprE8D0n5b?p=preview
You can try something like this (have not tested):
function baseController(callback){
return function($scope){
$scope.baseMethod = function(){
console.log('base method');
}
callback.apply(this, arguments);
}
}
app.controller('childController', baseController(function(){
}));
You can extend with a services, factories or providers. they are the same but with different degree of flexibility.
here an example using factory : 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
});
And here you can use the store function also:
<div ng-controller="myController">
<input ng-blur="myFactory.store()" />
</div>
You can directly use $controller('ParentController', {$scope:$scope}) Example
module.controller('Parent', ['$scope', function ($scope) {
//code
}])
module.controller('CtrlImplAdvanced', ['$scope', '$controller', function ($scope, $controller) {
//extend parent controller
$controller('CtrlImpl', {$scope: $scope});
}]);
You can use Angular "as" syntax combined with plain JavaScript inheritance
See more details here http://blogs.microsoft.co.il/oric/2015/01/01/base-controller-angularjs/
I wrote a function to do this:
function extendController(baseController, extension) {
return [
'$scope', '$injector',
function($scope, $injector) {
$injector.invoke(baseController, this, { $scope: $scope });
$injector.invoke(extension, this, { $scope: $scope });
}
]
}
You can use it like this:
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.
}]
)
);
}();
Pros:
- You don't have to register the base controller.
- None of the controllers need to know about the $controller or $injector services.
- It works well with angular's array injection syntax - which is essential if your javascript is going to be minified.
- You can easily add extra injectable services to the base controller, without also having to remember to add them to, and pass them through from, all of your child controllers.
Cons:
- The base controller has to be defined as a variable, which risks polluting the global scope. I've avoided this in my usage example by wrapping everything in an anonymous self-executing function, but this does mean that all of the child controllers have to be declared in the same file.
- This pattern works well for controllers which are instantiated directly from your html, but isn't so good for controllers that you create from your code via the $controller() service, because it's dependence on the injector prevents you from directly injecting extra, non-service parameters from your calling code.
I consider extending controllers as bad-practice. Rather put your shared logic into a service. Extended objects in javascript tend to get rather complex. If you want to use inheritance, I would recommend typescript. Still, thin controllers are better way to go in my point of view.
'Programing' 카테고리의 다른 글
Subversion 관리 파일 이름에서 @ 문자를 이스케이프 처리하는 방법은 무엇입니까? (0) | 2020.05.14 |
---|---|
ActiveRecord : 크기 대 개수 (0) | 2020.05.14 |
Django 템플릿에 주석을 넣는 방법 (0) | 2020.05.14 |
파이썬에서 문자열 날짜를 타임 스탬프로 변환 (0) | 2020.05.14 |
Mac OS X에서 gradle 설치 / 업그레이드 (0) | 2020.05.14 |