Passing data using ionic / angular modal using a separate template html file

I am developing a simple Ionic mobile app, although the answer probably lies with Angular. The app is really simple, displays a list of employees with an Add button that displays a modal form, allows the user to enter some data, click Save, and saves the data to the background storage of Firebase. It has 1 controller and simple service. I originally had an html template for modals inside script tags inside index.html and it all worked fine. When I decided to structure things and put the modal template in a separate html file, all of a sudden the data object assigned by ng-modal via the input fields no longer passes any data to the event handler to save the data, instead it is always undefined. Everything else works as it should, modal displays are fine,event handlers call the correct functions, etc. The only change is to move the input template to a separate file. I know this is probably something really simple, but life can't figure out why for me, and can't find any information about it elsewhere.

HTML file template for modal:

  <ion-list>

    <h1>Add Employee</h1>

    <div class="list list-inset">

      <ion-item>
        <label class="item item-input">
          <input type="text" placeholder="Employee Name" ng-model="data.employeeName">
        </label>

        <label class="item item-input">
          <input type="text" placeholder="Employee Age" ng-model="data.employeeAge">
        </label>
      </ion-item>

        <button class="button button-outline button-block button-balanced" 
          ng-click="addEmployee(true, data)">
            Save &amp; Add Another
        </button>

        <button class="button button-outline button-block button-positive" 
          ng-click="addEmployee(false, data)">
            Save
        </button>

        <button class="button button-outline button-block button-assertive" 
          ng-click="closeAddModal()">
            Cancel
        </button>

  </ion-list>

</ion-modal-view>

      

addEmployee event - data parameter is now always undefined. Works well with inline template:

$scope.addEmployee = function(retainModal, data) {
    var employee = {employeeName:data.employeeName,
                     employeeAge:data.employeeAge};
    employeeService.saveEmployee(employee);
    if (! retainModal) {
        $scope.closeAddModal();
    };
    data.employeeName = "";
    data.employeeAge = "";
}; 

      

+3


source to share


2 answers


Based on this question and other needs, I am creating a useful service.

See this post: Ionic modal service or see it in action: CodePen

(function () {
'use strict';

var serviceId = 'appModalService';
angular.module('app').factory(serviceId, [
    '$ionicModal', '$rootScope', '$q', '$injector', '$controller', appModalService
]);

function appModalService($ionicModal, $rootScope, $q, $injector, $controller) {

    return {
        show: show
    }

    function show(templateUrl, controller, parameters) {
        // Grab the injector and create a new scope
        var deferred = $q.defer(),
            ctrlInstance,
            modalScope = $rootScope.$new(),
            thisScopeId = modalScope.$id;

        $ionicModal.fromTemplateUrl(templateUrl, {
            scope: modalScope,
            animation: 'slide-in-up'
        }).then(function (modal) {
            modalScope.modal = modal;

            modalScope.openModal = function () {
                modalScope.modal.show();
            };
            modalScope.closeModal = function (result) {
                deferred.resolve(result);
                modalScope.modal.hide();
        };
        modalScope.$on('modal.hidden', function (thisModal) {
            if (thisModal.currentScope) {
                var modalScopeId = thisModal.currentScope.$id;
                if (thisScopeId === modalScopeId) {
                    deferred.resolve(null);
                    _cleanup(thisModal.currentScope);
                }
            }
        });

        // Invoke the controller
        var locals = { '$scope': modalScope, 'parameters': parameters };
        var ctrlEval = _evalController(controller);
        ctrlInstance = $controller(controller, locals);
        if (ctrlEval.isControllerAs) {
            ctrlInstance.openModal = modalScope.openModal;
            ctrlInstance.closeModal = modalScope.closeModal;
        }

        modalScope.modal.show();

        }, function (err) {
            deferred.reject(err);
        });

        return deferred.promise;
    }

    function _cleanup(scope) {
        scope.$destroy();
        if (scope.modal) {
            scope.modal.remove();
        }
    }

    function _evalController(ctrlName) {
        var result = {
            isControllerAs: false,
            controllerName: '',
            propName: ''
        };
        var fragments = (ctrlName || '').trim().split(/\s+/);
        result.isControllerAs = fragments.length === 3 && (fragments[1] || '').toLowerCase() === 'as';
        if (result.isControllerAs) {
            result.controllerName = fragments[0];
            result.propName = fragments[2];
        } else {
            result.controllerName = ctrlName;
        }

        return result;
    }

  } // end
})();

      

Using:



appModalService
 .show('<templateUrl>', '<controllerName> or <controllerName as ..>', <parameters obj>)
 .then(function(result) {
     // result from modal controller: $scope.closeModal(result) or <as name here>.closeModal(result) [Only on template]
 }, function(err) {
     // error
 });

      

You can use another service to centralize the configuration of all modals:

angular.module('app')
.factory('myModals', ['appModalService', function (appModalService){

var service = {
    showLogin: showLogin,
    showEditUser: showEditUser
};

function showLogin(userInfo){
    // return promise resolved by '$scope.closeModal(data)'
    // Use:
    // myModals.showLogin(userParameters) // get this inject 'parameters' on 'loginModalCtrl'
    //  .then(function (result) {
    //      // result from closeModal parameter
    //  });
    return appModalService.show('templates/modals/login.html', 'loginModalCtrl as vm', userInfo)
    // or not 'as controller'
    // return appModalService.show('templates/modals/login.html', 'loginModalCtrl', userInfo)
}

function showEditUser(address){
    // return appModalService....
}

}]);

      

+2


source


You need to attach your models to the area:

$scope.data.employeeName = "";
$scope.data.employeeAge = "";

      



... and similar every time you link to them.

0


source







All Articles