Мне интересно, что может быть хорошим способом поделиться директивой между контроллером. У меня есть два директивы для использования в разных контроллерах с другой конфигурацией первое, что я думал о используя:
//html
<body data-ng-controller="MainCtrl">
<div class="container">
<div data-ui-view></div>
</div>
</body>
//js
.controller('MainCtrl', function ($scope,$upload) {
/*File upload config*/
$scope.onFileSelect = function($files) {
for (var i = 0; i < $files.length; i++) {
var file = $files[i];
$scope.upload = $upload.upload({
url: 'server/upload/url',
method: 'POST',
data: {myObj: $scope.myModelObj},
file: file,
}).progress(function(evt) {
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
}).success(function(data, status, headers, config) {
console.log(data);
});
}
};
/* Datepicker config */
$scope.showWeeks = true;
$scope.minDate = new Date();
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.dateOptions = {
'year-format': "'yy'",
'starting-day': 1
};
$scope.format = 'MMM d, yyyy';
})
.controller('IndexCtrl', function ($scope) {
})
делая это, я могу использовать все функции в контроллере моих детей но я не очень люблю из-за проблем с столкновением. Поскольку вы не можете использовать услугу (вы не можете использовать $scope в сервисе), другие альтернативы могли бы сделать другую директиву или поместить код в блок выполнения но это совершенно одинаково с использованием родительского контроллера, поэтому о чем вы думаете?
ОБНОВЛЕНИЕ
Что вы думаете об этом подходе?
//outside of angular stauff
function MyTest(){
this.testScope = function(){
console.log('It works');
}
}
//inside a controller
$scope.ns = new MyTest();
//in the view
<p ng-click="ns.testScope()">ppp</p>
RIUPDATE это кажется лучшим вариантом:)
MyTest.call($scope);
Рассмотрим метод, описанный в этом сообщении: Расширение контроллеров AngularJS с использованием шаблона Mixin
Вместо того, чтобы копировать свои методы из службы, создайте базовый контроллер, который содержит эти методы, а затем вызовите расширение на своих производных контроллерах, чтобы их смешивать. Пример из сообщения:
function AnimalController($scope, vocalization, color, runSpeed) {
var _this = this;
// Mixin instance properties.
this.vocalization = vocalization;
this.runSpeed = runSpeed;
// Mixin instance methods.
this.vocalize = function () {
console.log(this.vocalization);
};
// Mixin scope properties.
$scope.color = color;
// Mixin scope methods.
$scope.run = function(){
console.log("run speed: " + _this.runSpeed );
};
}
Теперь мы можем микшировать AnimalController в DogController:
function DogController($scope) {
var _this = this;
// Mixin Animal functionality into Dog.
angular.extend(this, new AnimalController($scope, 'BARK BARK!', 'solid black', '35mph'));
$scope.bark = function () {
_this.vocalize(); // inherited from mixin.
}
}
И затем используйте DogController в нашем шаблоне:
<section ng-controller="DogController">
<p>Dog</p>
<!-- Scope property mixin, displays: 'color: solid black' -->
<p ng-bind-template="color: {{ color }}"></p>
<!-- Calls an instance method mixin, outputs: 'BARK BARK!' -->
<button class="btn" ng-click="bark()">Bark Dog</button>
<!-- Scope method mixin, outputs: 'run speed: 35mph' -->
<button class="btn" ng-click="run()">Run Dog</button>
</section>
Контроллеры в этом примере находятся в глобальном пространстве и включены в разметку следующим образом.
<script type="text/javascript" src="lib/jquery.js"></script>
<script type="text/javascript" src="lib/angular.js"></script>
<script type="text/javascript" src="app/controllers/animal-controller.js"></script>
<script type="text/javascript" src="app/controllers/dog-controller.js"></script>
<script type="text/javascript" src="app/controllers/cat-controller.js"></script>
<script type="text/javascript" src="app/app.js"></script>
Я не тестировал его, но я не понимаю, почему следующее не будет работать:
var myApp = angular.module('myApp', [])
.controller('AnimalController', ['$scope', 'vocalization', 'color', 'runSpeed', function ($scope, vocalization, color, runSpeed) { /* controller code here */}]);
.controller('DogController', ['$scope', '$controller', function($scope, $controller) {
var _this = this;
// Mixin Animal functionality into Dog.
angular.extend(this, $controller('AnimalController', {
$scope: scope,
vocalization: 'BARK BARK!',
color: 'solid black',
runSpeed:'35mph'
}));
$scope.bark = function () {
_this.vocalize(); // inherited from mixin.
}
}]);
см. docs для службы $controller
То, что вы хотите, ужасно.
Вы не хотели бы, чтобы ваши контроллеры знали что-либо друг о друге, не говоря уже о том, что у вас есть доступ к функции другого. Вы можете просто использовать Сервис для достижения этого. Что касается использования директив, не уверен, что именно вы хотите.
Что касается вашей второй вещи, вы можете так же легко сделать это
.service('MyTestService', function(){
return {
testScope: function(){
console.log('It works');
}
};
})
.controller('MyController', ['$scope', 'MyTestService', function($scope, MyTestService){
$scope.testScope = MyTestService.testScope;
}])
и на ваш взгляд:
<p ng-click="testScope()">ppp</p>
очевидное, но блестящее решение (может быть)
(function(window, angular, undefined) {
'use strict';
angular.module('ctrl.parent', [])
.run(function ($rootScope) {
$rootScope.test = 'My test'
$rootScope.myTest = function(){
alert('It works');
}
});
})(window, angular);
angular.module('app',['ctrl.parent'])
.controller('ChildCtrl', function($scope){
});
Это легко и чисто и не видит никакого недостатка (это не глобально)
ОБНОВЛЕНИЕ
'use strict';
(function(window, angular, undefined) {
'use strict';
angular.module('ctrl.parent', [])
.controller('ParentController',function (scope) {
scope.vocalization = '';
scope.vocalize = function () {
console.log(scope.vocalization);
};
});
})(window, angular);
angular.module('app',['ctrl.parent'])
.controller('ChildCtrl', function($scope,$controller){
angular.extend($scope, new $controller('ParentController', {scope:$scope}));
$scope.vocalization = 'CIP CIP';
});
немного аккуратно и работает CIP CIP:)
Я закончил с:
//service
.service('PostUploader',function($upload){
var that = this;
var fileReaderSupported = window.FileReader !== null;
this.notify = null;
this.success = null;
this.showAlert = false;
this.avatar = '';
this.onFileSelect = function($files) {
var $file = $files[0];
var filename = $file.name;
this.avatar = filename;
var isImage = /\.(jpeg|jpg|gif|png)$/i.test(filename);
if(!isImage){
this.showAlert = true;
return;
}
this.showAlert = false;
if (fileReaderSupported && $file.type.indexOf('image') > -1) {
var fileReader = new FileReader();
fileReader.readAsDataURL($file);
fileReader.onload = that.notify;
}
$upload.upload({
url :'/api/post/upload',
method: 'POST',
headers: {'x-ng-file-upload': 'nodeblog'},
data :null,
file: $file,
fileFormDataName: 'avatar'
})
.success(that.success)
.progress(function(evt) {
})
.error(function(data, status, headers, config) {
throw new Error('Upload error status: '+status);
})
};
this.closeAlert = function() {
this.showAlert = false;
};
})
//controller
/* Uploader post */
$scope.dataUrl = null;
$scope.avatar = PostUploader.avatar;
$scope.showAlert = PostUploader.showAlert;
$scope.onFileSelect = PostUploader.onFileSelect;
$scope.closeAlert = PostUploader.closeAlert;
PostUploader.notify = function(e){
$timeout(function() {
$scope.dataUrl = e.target.result;
});
};
PostUploader.success = function(data, status, headers, config) {
$timeout(function() {
$scope.post.avatar = data.url;
});
}
$scope.$watch('avatar',function(newVal, oldVal){
if(newVal) {
$scope.avatar = newVal;
}
});
$scope.$watch('showAlert',function(newVal, oldVal){
$scope.showAlert = newVal;
$scope.dataUrl = null;
});
Я сделал это, потому что я должен делать то же самое в создании сообщения и редактирования сообщения, но в целом У меня такой же повторяющийся код!:)
Единственное, что есть в коде, имеет меньше логики.