离子:从自定义模态窗体的控制器中的对象访问

时间:2015-11-04 19:12:14

标签: angularjs ionic-framework ionic angularjs-forms

我已创建codepen来显示问题。

使用服务appModalService时,vm对象会直接替换为FormController对象,因此vm的所有属性都无法在模板中访问与vm对象关联的控制器变得完全没用。

appModalService上的讨论(推理)可以在ionic form中找到。

我在这里添加了代码以供参考。有关解决此问题的任何建议吗?

HTML:

<html ng-app="ionicApp">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">

  <title>Ionic modal service</title>

  <link href="http://code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">
  <script src="http://code.ionicframework.com/nightly/js/ionic.bundle.js"></script>

</head>

<body ng-controller="AppCtrl as vm">

  <ion-content padding="true" ng-class="{'has-footer': showFooter}">
    <div class="row">
      <div class="col">
        <button ng-click="vm.showNonWorkingForm()" class="button button-assertive button-block">
          Show Non Working Form (using appModalService)
        </button>
      </div>
    </div>
    <div class="row">
      <div class="col">
        <button ng-click="vm.showWorkingForm()" class="button button-assertive button-block">
          Show Working Form (using ionic ModalService)
        </button>
      </div>
    </div>

  </ion-content>

  <script id="non-working-form-modal.html" type="text/ng-template">
    <ion-modal-view>
      <ion-header-bar class="bar bar-header bar-positive">
        <h1 class="title">Form</h1>
        <button class="button button-clear button-primary" ng-click="vm.closeModal()">Close</button>
      </ion-header-bar>
      <ion-content>
        <form novalidate name="vm.f" ng-submit="vm.submit()">
          <div class="list">
            <label class="item item-input">
              <input placeholder="text" type="text" name="sometext" ng-model="vm.sometext" required>
            </label>
          </div>
          <button type="submit" class="button button-block">
            Submit
          </button>
        </form>
        {{ vm }}
      </ion-content>
    </ion-modal-view>
  </script>

  <script id="working-form-modal.html" type="text/ng-template">
    <div class="modal" ng-controller="WorkingCtrl as vm">
      <ion-header-bar class="bar bar-header bar-positive">
        <h1 class="title">Form</h1>
        <button class="button button-clear button-primary" ng-click="closeModal()">Close</button>
      </ion-header-bar>
      <ion-content>
        <form novalidate name="vm.f" ng-submit="vm.submit()">
          <div class="list">
            <label class="item item-input">
              <input placeholder="text" type="text" name="sometext" ng-model="vm.sometext" required>
            </label>
          </div>
          <button type="submit" class="button button-block">
            Submit
          </button>
        </form>
        {{ vm }}
      </ion-content>
    </div>
  </script>

</body>

</html>

JS

angular.module('ionicApp', ['ionic'])
  .controller('NonWorkingCtrl', ['$scope', 'parameters', function($scope, parameters) {
    var vm = this;
    /* placeholder for the FormController object */
    vm.f = null;
    vm.sometext = 'Added Some text';
    vm.submit = function() {
        if (vm.f.$valid) {
          alert('NonWorkingCtrl Valid');
        } else {
          alert('NonWorkingCtrl InValid');
        }
      }
      /* additional fields */
    vm.field1 = 'field1';
    vm.field2 = 'field2';
    vm.field3 = 'field3';
    vm.field4 = 'field4';
    vm.field5 = 'field5';
    vm.field6 = 'field6';
    vm.field7 = 'field7';
  }])
.controller('WorkingCtrl', ['$scope', function($scope) {
    var vm = this;
    /* placeholder for the FormController object */
    vm.f = null;
    vm.sometext = 'Added Some text';
    vm.submit = function() {
        if (vm.f.$valid) {
          alert('WorkingCtrl Valid');
        } else {
          alert('WorkingCtrl InValid');
        }
      }
      /* additional fields */
    vm.field1 = 'field1';
    vm.field2 = 'field2';
    vm.field3 = 'field3';
    vm.field4 = 'field4';
    vm.field5 = 'field5';
    vm.field6 = 'field6';
    vm.field7 = 'field7';
  }])
.controller('AppCtrl', ['$scope', 'appModalService', '$ionicModal', function($scope, appModalService, $ionicModal) {
    var vm = this;
    vm.showNonWorkingForm = function() {
      appModalService.show('non-working-form-modal.html', 'NonWorkingCtrl as vm');
    };

    vm.showWorkingForm = function() {
      $ionicModal.fromTemplateUrl('working-form-modal.html', {
        scope: $scope,
        animation: 'slide-in-up'
      }).then(function(modal) {
        $scope.modal = modal;
        $scope.modal.show();
      });
      $scope.closeModal = function() {
        $scope.modal.hide();
        $scope.modal.remove();
      };
    }
  }])
.factory('appModalService', ['$ionicModal', '$rootScope', '$q', '$injector', '$controller', function($ionicModal, $rootScope, $q, $injector, $controller) {

    return {
      show: show
    }

    function show(templeteUrl, controller, parameters, options) {
      // Grab the injector and create a new scope
      var deferred = $q.defer(),
        ctrlInstance,
        modalScope = $rootScope.$new(),
        thisScopeId = modalScope.$id,
        defaultOptions = {
          animation: 'slide-in-up',
          focusFirstInput: false,
          backdropClickToClose: true,
          hardwareBackButtonClose: true,
          modalCallback: null
        };

      options = angular.extend({}, defaultOptions, options);

      $ionicModal.fromTemplateUrl(templeteUrl, {
        scope: modalScope,
        animation: options.animation,
        focusFirstInput: options.focusFirstInput,
        backdropClickToClose: options.backdropClickToClose,
        hardwareBackButtonClose: options.hardwareBackButtonClose
      }).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()
          .then(function() {
            modalScope.$broadcast('modal.afterShow', modalScope.modal);
          });

        if (angular.isFunction(options.modalCallback)) {
          options.modalCallback(modal);
        }

      }, 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;
    }

  }]);

1 个答案:

答案 0 :(得分:0)

@NEB我在离子形式方面遇到了类似的问题。我在IonicForum DiscGolfer17

上找到了here的答案

基本上,离子的<content>指令创建了它自己的孤立范围。正如形式和离子的<ion-modal-view>指令一样,我相信。

为了让您的ng-click="vm.closeModal()"工作,您需要在$parent前面vm链接ng-click="$parent.vm.closeModal()"

这告诉它继承它的父母$scope。这是working fork of your Plunk