MVC violation in Ionic(angular) framework with $io

2019-05-23 06:38发布

When working with the $ionicModal in Ionic Framework, I noticed a lot of people instantiate the Modal inside the controller and pass the controller scope to the Modal. Like so,

   $ionicModal.fromTemplateUrl("views/call_options_view.html", function ($ionicModal) {

        $scope.menu = $ionicModal;

   }, {

        scope: $scope,
        animation: "slide-in-up"

   });

Doing this allows the modal to invoke methods in the controller scope. Is there some way we can give a separate controller to the Modal? Right now, using the controller scope, isn't there a MVC violation? The controller owns two views. Suppose I want the same modal available on another controller, then I would have to duplicate my functionality for the modal on both the controllers. MVC is supposed improve code reuse. So essentially, I want to re-enforce MVC by giving my modal a separate controller.

One way I thought of fixing this is by putting the modal in the Root Controller. Doing so, will make it accessible from all the child controllers and the functionality for the modal will only be available in the root controller. I still don't like this fix, cause i don't want to clutter my root controller with too much logic.

Any other suggestions?

1条回答
三岁会撩人
2楼-- · 2019-05-23 07:06

I stumbled on your question while trying to come up with a solution similar to your concern.

Because I had a problem regarding navigation in my routes, I decided to use $ionicModal to show a view of another state in a modal view. I came up with a solution I crafted there (but I did not implement it for my working context yet) that should work in my case, while I'm not really satisfied with it.

To summarize, all my states are nested under tabs; when I am in the tabs.home state, I want to directly show the tabs.settings.sub state. However, tabs.settings.sub relies on data populated by its parent state tabs.settings. Hence my problem with giving the scope of my current state (tabs.home) to tabs.settings.sub.

My modal uses a template that will include the template of my view:

<script id="templates/modal.html" type="text/ng-template">
  <ion-modal-view>
    <ng-include src="templateUrl" ng-controller="controller"></ng-include>
  </ion-modal-view>
</script>

I can then reuse the view from the state. Regarding the scope, I used $scope.new(true) to isolate it, and populated it with data required by my modal template:

var subState = $state.get ('tabs.settings.sub');
var subScope = $scope.$new (true); // true: isolate
subScope.title = 'Sub';
subScope.templateUrl = subState.templateUrl;
subScope.controller = function () {
  if (subState.controller)
    return $controller (subState.controller, {$scope:subScope});
  return null;
};

The modal is instantiated using this scope (that's one problem to my opinion: mixing the scope of the modal and the scope of the controller). The controller has to be a function that returns the appropriate controller.

$ionicModal.fromTemplateUrl ('templates/modal.html', {
  scope: subScope
}).then (function (modal) {
  modal.show ();
});

The major problem with my solution is to transit data up to the controller of the view to show (in this case SubCtrl). But it is more narrowed to my specific context: my modal is not aware of the chain of inheritance of controllers adn states, because this is handled by UI router.

I don't know if it is possible to access the state associated to a controller (the usual pattern seems to be to use $state.parent, but this cannot be used here, as mentioned by the UI router wiki).

The workaround I use here (this is the part I am not satisfied with) is to federate data through the states:

.state ('tabs.settings', {
  data: { status: 'valid' }
}

I have access to it when creating my modal:

subScope.status = subState.data.status;

And I have access to it from the parent controller:

$scope.status = $state.current.data.status;
查看更多
登录 后发表回答