How to extend a bootstrap ui controller - angularjs

I have included the bootstrap ui module in my angular project and now I want to extend for example the datepicker controller 'UibDatepickerController' in the 'ui-bootstrap-tpls.js' with further functions.
Okay, I could edit the ui bootstrap file, but that is not that what I want.
I want a modularized file (maybe an own directive) so that there are no big problems when a ui bootstrap update is incoming.
Is that possible? What is best practice?

You can try injecting $controller and extending like this:
app.directive('myUiDirective', function ($controller) {
return {
link: function (scope, iElem, iAttr) {
angular.extend(this, $controller('UibDatepickerController', {$scope: scope}));
}
});
However I am not sure if you will be able to get controller from different module (in this case, from ui.bootstrap).

Related

Angular JS - Get the component controller instance manuallly

In Angular JS I would want to get a component controller instance manually, that ideally is achieved through the require binding in component. I have a requirement where in I am outside the Angular JS component environment and I cannot use require.
// Sample require binding
module.component('superHeros', {
template: `
<h2>
Super Heros Component
</h2>
`,
require: {
parentCtrl: '^heroList'
},
controller: superHerosControler
});
Though I thought this could be achieved with $injector of angular but does not seem to work (throws Unknown provider).
So I want to do this
require: {
parentCtrl: '^heroList'
}
like this this.requiredController = $injector.get(<componentName>);
I understand that this works perfectly for Services or factories. Is there a way to achieve this or a workaround that can essentially get me an component controller instance ?
Plunker here
Any help would be appreciated. Thanks

AngularJS - What is expected behaviour of two directives with the same name but in different modules?

Of course, I can check it myself.
It's more conceptual/architectural question and why it was build so.
angular.module('appmodule1').directive('mydir', function(){});
angular.module('appmodule2').directive('mydir', function(){});
so what should we expect from mydir?
UPD:
dependencies between the modules:
angular.module('app',['appmodule1', 'appmodule2'])
or
angular.module('appmodule1', ['appmodule2']);
One trivial thing is that if your module only directly/indirectly loads only one of the module then that directive factory only will be used. But if your question is what if both the modules are loaded say for example angular.module('app',['appmodule1', 'appmodule2']) and your application is bootstrapped with the module app then the directive factories will be added together, i.e directive factories are additive and such component when used will render with both the factories.
angular.module('app1', []).directive('mydir', function() {
return {
restrict: 'E',
link: function() {
console.log("App1");
}
}
});
angular.module('app2', []).directive('mydir', function() {
return {
restrict: 'E',
link: function() {
console.log("App2");
}
}
});;
angular.module('app', ['app1', 'app2']).config(function($provide) {
$provide.decorator('ngRequiredDirective', function($delegate) {
console.log($delegate); //Check the console on the configuration you will see array of 2 configurations
return $delegate;
})
});;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div ng-app="app">
<mydir></mydir>
<test ng-required="true"></test>
</div>
Generally the scoping, template etc cannot be specified in both (Rules are same as when an element has more than one directives mentioned) and these kind of directives are generally defined in the same module (or even in a different module) with intend and for special purpose. For example angular internally has a directive with the selector select which works along with ng-options directive, now say in your application you want to convert all the select to a bootstrap select option or with ng-repeated material select. You can abstract them out an still create another directive with the selector select and add your logic to render it by parsing the ng-options expression and render the new dropdown.
An example is within angular itself, the way ng-required and other similar directives are implemented, see this answer for example. You can check it out by doing a console log of ng-required directive factory as below.
.config(function($provide) {
$provide.decorator('ngRequiredDirective', function($delegate) {
console.log($delegate); //Check the console on the configuration you will see array of 2 configurations
return $delegate;
})
});
Why it was built?
By bet would be on extensibility and dividing different responsibility in different factories.
So in short if at all you have multiple directive factories for the same selector it should not be accidental, but created with clear purpose, otherwise it could turn out to be a disaster!
It will depend under which module the directive is instantiated. If you're under the appmodule1, the corresponding directive would be used. There would be no conflict here, unless I'm missing something.

Nested directive not compiling

I have a custom directive I have created that loads a template into a modal window. The modal window is a template itself and is able to run my custom directive without issues. That template that is loaded into the modal contains another directive which creates a select list using angular-selectize. Here is my directive:
var dynamicTemplate = function($templateRequest, $compile) {
return {
restrict: "E",
link: function(scope, element, attrs) {
var modalOptions = JSON.parse(attrs.modalOptions);
$templateRequest(modalOptions.Url).then(function(html) {
$elem = $compile(html)(scope);
element.append($elem);
});
}
}
}
The HTML is getting loaded correctly, but the selectize directive is not initializing .
I have also tired this inside the then method:
element.html(html)
$compile(element.contents())(scope);
That gave me the same result.
The issue I am having is I am receiving this message after the compilation of the HTML:
TypeError: element.selectize is not a function
Here is the plunk I am working with.
If you want angular.element to use jQuery you have to include jQuery in page before angular loads.
Demo works fine once you change script order
Updated demo
First solution
You have to include jQuery.js before Angular.js in index.html. This magic makes angular.element to use jQuery.
Solution 1
Second solution
You may replace element.selectize with $(element).selectize in angular-selectize.js on line 97. This makes angular-selectize script to use jQuery's selector instead of angular's.
Solution 2
Include jQuery in the page before Angular loads. Then angular.element will use jQuery.

How to initialize an angularjs module by passing values/configurations

I'm new to Angular and I'm from jQuery background.
My question is How to initialize angularjs module by passing values/configurations. Here is the scenario.
We will have core module (which will load/integrate other modules based on the need)
We're planned to create a module for each major feature
We need to load the module's based on the need
The only one approach till now I'm able to figure out is below,
Creating a custom attribute/tag directive
Create a custom controller to initialize the module
Create a new variable in the $scope and specify the configuration options
With this approach I'm able to access the options specified in the controller scope using the link function in the directive. The code is something like below,
// Main angular module
angular.module('myApp').directive('myDirective', function() {
return {
restrict: 'EA',
scope: {
configOptions: '='
},
link: function(scope, element, attribute) {
// configurations will be available in scope.configOptions
console.log(scope.configOptions);
}
};
});
// Module & Controller to initialize the main module.
angular.module('consumerApp', ['myApp']).controller('HomeCtrl', ['$scope', function($scope) {
$scope.configOptions= {
path: "xxxxx",
height: xxx,
width: xxx
};
}]);
// HTML code
<div ng-controller='HomeCtrl'>
<div myDirective></div>
</div>
Is this valid/best approach or do we have better solutions to achieve the same. On further note is there any way available to initialize the app like we do in jQuery.

kendo ui angular js grid ng-repeat

I m trying to use Kendo grid in my angular js app. I m creating a directive so I can use it in different tables among the application. Once the ng-repeat renders the dom I want to call:
element.kendogrid().
Since there is no post-render callback for ng-repeat, some people suggest using two directives:
1-
angular.module('app')
.directive('rowDirective', function () {
return function(scope, element){
if (scope.$last){
scope.$emit('LastElementMessage');
}
};
});
2-
angular.module('app')
.directive('tableDirective', function () {
return function(scope, element){
scope.$on('LastElementMessage', function(event){
$(element).kendoGrid({
scrollable: true,
sortable: true,
});
});
}
});
This approach works fine and everything is executed in the order it should. The ng-repeat works fine by it self, which means it renders the items in the right order but when I use the kendo-grid, it renders this: {{customer.CustomerID}} inside the grid. Has anyone gone through something like this ?
Well, perhaps you should take a look at Angular Kendo UI project at http://kendo-labs.github.io/angular-kendo/ - it does rather good job of "marrying" Kendo UI with AngularJS.
See http://demos.telerik.com/kendo-ui/grid/angular.
There are specific custom directives that enable kendo ui to play nicely with angular js. E.G. k-data-source, k-columns, k-selectable, k-pageable. These should be included in the latest version of kendo ui. Just make sure to include "kendo.directives" as a dependency on your top level-module :
var MyModule = angular.module('MyModule', ["ngRoute", "kendo.directives"]);

Resources