0

I have inherited some AngularJS code. It has this

function MainCtrl($scope) 
{
  // code goes here
};

angular
    .module('inspinia')
    .controller('MainCtrl', MainCtrl)

Now I want to add a custom controller which combines a datepicker and timepicker into one control. The GitHub project is here and there is a demo Plunk here.

The demo Punk declares its controller as

var app = angular.module('app', ['ui.bootstrap', 'ui.bootstrap.datetimepicker']);

app.controller('MyController', ['$scope', function($scope) {

How do I add that into my existing controller? What is the combined declaration? Preferably one that I can use it with ng-stricti-di on my ng-app.


[Update] here's my best guess, which I can't test until I get home in 10 hours or so. How does it look?

var myApp=angular.module('myApp', ['$scope','ui.bootstrap','ui.bootstrap.datetimepicker']); 

myApp.controller('MainCtrl', function($scope) 
{
    // code goes here, and can use ui.bootstrap and ui.bootstrap.datetimepicker
    // which were injected into the app's module
}]);

[Update 2[ When I change it to

angular
    .module('inspinia' ['ui.bootstrap', 'ui.bootstrap.datetimepicker'])
        .controller('MainCtrl', MainCtrl)

I get

Error: [$injector:nomod] http://errors.angularjs.org/1.5.0/$injector/nomod?p0=undefinedError: [$injector:nomod] http://errors.angularjs.org/1.5.0/$injector/nomod?p0=undefined

Despue index.html having

<script src="js/bootstrap/bootstrap.min.js"></script>

How do I get this project to use ui boostrap and its datepicker?

8
  • 1
    The question doesn't seem to be very clear. Is there a reason you aren't able to add the same dependencies to your application? Are you getting an error somewhere? Commented Mar 22, 2016 at 19:23
  • I am too much of a noob. The two seem to mix and match styles. If it is straightforward, could you show me how? Thanks! Commented Mar 22, 2016 at 19:25
  • 1
    The ui.bootstrap and ui.bootstrap.datetimepicker are both modules. That means they can only be injected into other modules ( in your examples either MyApp or inspinia). You don't need to change your controller at all, based on everything I've seen so far. Read over modules here: docs.angularjs.org/guide/module Commented Mar 23, 2016 at 13:40
  • 1
    I've updated the answer to try to be clearer now that I see where you are struggling. Commented Mar 23, 2016 at 14:13
  • 1
    In the code snippet you have pasted in Update 2, you are missing a comma (,) between module name 'inspinia' and its dependency list. That could be reason for the error. Commented Mar 29, 2016 at 5:49

3 Answers 3

4

Please review these steps:

  1. You don't need to inject your $scope in your app declaration just inject external modules you want to use, for this case: 'ui.bootstrap' and 'ui.bootstrap.datetimepicker'.

    angular.module('myApp', ['ui.bootstrap','ui.bootstrap.datetimepicker'])
    

    What is the combined declaration?

    Because 'ui.bootstrap.datetimepicker' depends only on 'ui.bootstrap.dateparser' and 'ui.bootstrap.position' but you need also the bootstrap templates and functionality that are included into the ui.bootstrap-tpls.js.

  2. Make sure to include the above files required in you index.html

    <link rel="stylesheet" ref="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />     
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.1.0/ui-bootstrap-tpls.js"></script>
    <!-- make sure you download this file from the github project -->
    <script src="datetime-picker.js"></script>
    
  3. How do I add that into my existing controller?

    When you declare your controller this inherit all module dependencies you had declared (injected) for the app, so you don't need to do this again. In your controller you should create an object literal to store the date-time selected for the user and a variable to control when the date-picker is open, like this:

    angular.module('myApp').controller('MainCtrl', ['$scope', function($scope) {
     $scope.myDatetime = {
       dateSelected: new Date(),
       isOpen: false
     }
    }]);
    
  4. Call the date-time picker directive in your html:

    <html ng-app-="myApp">
    <head> .... </head>
    <body ng-controller="MainCtrl">
    <div class="input-group">
       <input type="text" class="form-control" datetime-picker="MM/dd/yyyy HH:mm" ng-model="myDatetime.dateSelected" is-open="myDatetime.isOpen" />
        <span class="input-group-btn">
           <button type="button" class="btn btn-default" ng-click="myDatetime.isOpen = !myDatetime.isOpen"><i class="fa fa-calendar"></i></button>
        </span>
    </div>
    </body>
    </html>
    

    I hope this help you.

Sign up to request clarification or add additional context in comments.

1 Comment

I thnak you very much for taking the tome ot try to help me (+1). Alas, when I tarted again with an empty skeleton project and followed your instructions, the datepicker does not pop-up :-(
3

Based on your comment under the question, your confusion is with the way the two pieces of code handle their dependency injection. So before I go further, if you haven't read the documentation on dependency injection, then stop right here and go read it. It will have all of your answers and more and it's something you need to know if handling Angular for longer than five minutes.

To answer the specific case you have, the top code you listed uses implicit injection for the controller which works but is not safe for minification nor is it recommended. The code sample you found uses array dependency inject for the controller which is better and safe for minification. The app declaration in the second sample is just standard module dependency injection and shouldn't look any different than what you already have in your application.

So to use the code you found all you have to do is add the correct module dependencies to your app something like:

angular.module('inspinia', ['ui.bootstrap', 'ui.bootstrap.datetimepicker']);
angular.module('inspinia').controller('MainCtrl',MainCtrl);
function MainCtrl($scope) { }

Your controller appears to already have the correct dependencies so it doesn't need to be changed (which is say it doesn't need anything outside of $scope). I used the code from your first example to show how your current code would be updated but ideally you would use the second version of dependency inject for your controller.


The update you have with the error is because the ui.bootstrap module is not part of bootstrap but part of the angular-bootstrap project. You need to include those js in your page.


It would be remiss of me if I didn't go ahead and mention there is a third way to do dependency injection using the $inject service. It is preferred in a number of popular style guides because it is easy to use a task runner to automate. This is arguably the best option to use for this reason.

6 Comments

Nope, sorry, I can't quite figutre it out from that. Do you mean that I should .controller('MainCtrl', MainCtrl, ['ui.bootstrap', 'ui.bootstrap.datetimepicker']) ?
No, that goes on the module declaration just like the example. So you would have code somewhere like angular.module('inspinia', []) that you would add your application dependencies to.
I do appreciate that you are trying to help me by forcing me to learn, but, it's very late over here... couldn't you, pretty please, just post the code? ;-) Sorry, I have to go to sleep now
I've updated the question but I'm not sure if I can be much more clear than this. Maybe some fresh eyes and/or coffee are in order.
I don't have the links since I'm on my phone but I updated the answer. Basically you are not including the correct js for what you are trying to use.
|
1
+100

Here is minimal app, that you will need to use this datepicker

Html:

<body ng-app="inspinia">
  <div ng-controller="MainCtrl as ctrl">
    <h1>Datepicker Demo</h1>
    <div class="row">
      <div class="col-md-6">
        <p class="input-group">
          <input type="text" class="form-control" uib-datepicker-popup ng-model="ctrl.dt" is-open="ctrl.opened" close-text="Close" />
          <span class="input-group-btn">
              <button type="button" class="btn btn-default" ng-click="ctrl.open()"><i class="glyphicon glyphicon-calendar"></i></button>
            </span>
        </p>
      </div>
    </div>
  </div>
</body>

JavaScript:

(function() {
  'use strict';
  angular.module('inspinia', ['ui.bootstrap']);
  angular.module('inspinia').controller('MainCtrl', MainCtrl);

  function MainCtrl() {

    this.open = function() {
      this.opened = true;
    };

    this.opened = false;
  }
})();

Here I created a plunker for you, so you can try:

http://plnkr.co/edit/jEwT39sKcKtr8jbQa0uc?p=preview

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.