1

I'm very much naive in angular and typescript. I'm trying to create a popup on clicking a image. I found a SO link which answers this question using IMODALSERVICE.

How to use angular-ui-bootstrap (modals) in typescript?

However for some reason ng.ui.bootstrap.IModalService type is not recognized in project. Am I doing anything wrong or the SO post has some mistakes. I did add all the angular dependencies in my project.

Community
  • 1
  • 1
rampuriyaaa
  • 4,926
  • 10
  • 34
  • 41
  • Did you add a definition for angular-ui-bootstrap? https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/angular-ui-bootstrap – Daan van Hulst Feb 09 '16 at 11:44

2 Answers2

3

For your programming environment (IDE like Visual Studio) to be able to recognize types you need to add typescript definitions.

The best way to get the angular-bootstrap-ui is using the TSD tool

Then with the command line at your project you could run the command: tsd install angular-ui-bootstrap --resolve --save

and essentially that would "install" the file angular-ui-bootstrap.d.ts in your typings folder. If your development environment does not detect it simply add /// <reference path="../../../typings/angular-ui-bootstrap/angular-ui-bootstrap.d.ts" /> at the top of your typescript file. Notice that the path must match depending on your folder structures (that's only an example).

After that I personally like to wrap the angular-ui-bootstrap modal in a service, so I'd create a template confirmation-modal.html as follows:

<div>
    <div class="modal-header">
        <h3 class="modal-title">{{ modal.title }}</h3>
    </div>
    <div class="modal-body">
        {{ modal.bodyText }}
    </div>
    <div class="modal-footer">
        <button class="btn btn-primary" type="button" ng-click="modal.ok()">OK</button>
        <button class="btn btn-default" type="button" ng-click="modal.cancel()">Cancel</button>
    </div>
</div>

That's the view for the modal. It's a basic confirmation dialog with buttons OK and Cancel, a title and a body text. You can get the idea though.

Then I'd create a service modal.service.ts with a function to show a confirmation dialog that accepts a title, a bodyText and a callback function for the OK button and optionally for the CANCEL button. For example:

/// <reference path="../../../typings/angular-ui-bootstrap/angular-ui-bootstrap.d.ts" />
module app.services {
    "use strict";

    interface IModalParams {
        title: string;
        bodyText: string;
        onOk(): void;
        onCancel(): void;
    }

    interface IModalConfirmationInstance {
        title: string;
        bodyText: string;
        ok(): void;
        cancel(): void;
    }

    export interface IModalService {
        showConfirmDialog(title: string, bodyText: string, onOk: () => void, onCancel?: () => void): void;
    }

    class ModalInstanceController implements IModalConfirmationInstance {

        public static $inject = [
            "$uibModalInstance",
            "modalParams"
        ];

        constructor(
            private $uibModalInstance: angular.ui.bootstrap.IModalServiceInstance,
            private modalParams: IModalParams) {
        }

        public title: string = this.modalParams.title;

        public bodyText: string = this.modalParams.bodyText;

        public ok(): void {
            this.modalParams.onOk();
            this.$uibModalInstance.close();
        }

        public cancel(): void {
            if (this.modalParams.onCancel) {
                this.modalParams.onCancel();
            }
            this.$uibModalInstance.dismiss();
        }
    }

    class ModalService implements IModalService {
        constructor(
            private $uibModal: angular.ui.bootstrap.IModalService) {
        }

        public showConfirmDialog(title: string, bodyText: string, onOk: () => void, onCancel?: () => void): void {
            console.log("show modal");

            let modalParams: IModalParams = {
                title: title,
                bodyText: bodyText,
                onOk: onOk,
                onCancel: onCancel 
            };

            let modalInstance = this.$uibModal.open({
                animation: true,
                templateUrl: "/app/confirmation-modal.html",
                controller: ModalInstanceController,
                controllerAs: "modal",
                size: null, // default size
                resolve: {
                    modalParams: () => modalParams
                }
            });
        }
    }

    factory.$inject = [
        "$uibModal"
    ];

    function factory(
        $uibModal: angular.ui.bootstrap.IModalService): IModalService {
        return new ModalService($uibModal);
    }

    angular
        .module("app.services")
        .factory("app.services.ModalService", factory);
}

Notice that in addition to the service, in the same file I have created a controller to handle the modal instance and that the resolve property is passing an object to that controller with all the necessary parameters wrapped in it. Also notice that I don't like using $scope and I prefer using the controller as approach. That's why I have the controller property as controllerAs defined as "modal" so that in the template modal view I can refer to the controller with the word modal (or whatever you choose).

Now all my functionality is wrapped in a service, so I can show my confirmation dialog modal from anywhere where my service has been injected. For example, let's say I have a view attached to a controller somewhere..

<div ng-controller="app.foo.MyController as myCtrl">
  <!-- some things and below a button to delete something with confirmation (or whatever) -->
  <button ng-click="myCtrl.delete()">
     <span class="fa fa-trash-o" aria-hidden="true"></span>
  </button>
</div>

Then in that MyController I could have for example the function that gets triggered when clicking on the delete button:

module app.foo {
    "use strict";

    interface IMyControllerScope {
        delete(): void;
    }

    class MyController  implements IMyControllerScope {
        public static $inject = ["app.services.ModalService"];

        constructor(private modalService: app.services.IModalService) {
        }

        public delete(): void {
            this.modalService.showConfirmDialog("Delete Things", "Are you sure?",
                () => {
                    console.log("The button OK has been click. Do things");
                    // some actions to execute when the button OK has been pressed
                });
        }
    }

    angular
        .module("app.foo")
        .controller("app.foo.MyController ", MyController );
}

Notice how I inject the service that wraps the modal functionality and the only thing I have to do is provide a title and body for the modal and the action to execute when OK (and optionally Cancel) is clicked.

diegosasw
  • 13,734
  • 16
  • 95
  • 159
0

Make sure you've installed angular-ui-bootstrap.d.ts https://www.nuget.org/packages/angular-ui-bootstrap.TypeScript.DefinitelyTyped/

if you're using visual studio usually package get install in Scripts/typings/

user585014
  • 157
  • 5
  • 14