0

I have a popup form where it's having lot of tabs.

Its' like this :

index.js

vm.openCreateOrEditPropertyModal = function (resolveProperty) {
    var modalInstance = $uibModal.open({
        templateUrl: '~/App/tenant/views/propertymanagement/createOrEditPropertyModal.cshtml',
        controller: 'tenant.views.propertymanagement.createOrEditPropertyModal as vm',
       resolve: {
              resolveProperty: function () {
              return resolveProperty;
                }
               }
                });
        };

Tabs are like this :

createOrEditPropertyModal.cshtml

<uib-tabset class="tab-container tabbable-line" type="pills">
  <uib-tab heading="@L("PropertyInformation")">
       <div ng-include="'~/App/tenant/views/propertymanagement/tabs/propertyForm.cshtml'"></div>
      </uib-tab>
</uib-tabset>

createOrEditPropertyModal.js

(function () {
    appModule.controller("tenant.views.propertymanagement.createOrEditPropertyModal", [
        "$scope", "resolveProperty", "localStorageService", "$uibModalInstance", function ($scope, resolveProperty, localStorageService, $uibModalInstance) {

            var vm = this;


            //to close the pop up
            vm.cancel = function () {
                $uibModalInstance.close();
            };
        }
    ]);
})();

propertyForm.cshtml

<div ng-controller="tenant.views.propertymanagement.tabs.propertyForm as vm">
    <button type="button" ng-click="vm.cancel()">@L("Close")</button>
</div>

propertyForm.js

(function () {
    appModule.controller("tenant.views.propertymanagement.propertyForm", [
        "$scope", "resolveProperty", "localStorageService", function ($scope, resolveProperty, localStorageService) {

            var vm = this;



        }
    ]);
})();

Above set up is working fine.Now I need to access cancel() method on the createOrEditPropertyModal.js file from the child form (i.e. propertyForm.cshtml).But it's not being fired.Can you tell me how to do that ? I have tried like this ng-click="$parent.cancel()".But it's not working.

Sampath
  • 63,341
  • 64
  • 307
  • 441

2 Answers2

1

I can think of three possible solutions:

  1. It's because the cancel function is not on the $parent scope, but on the parent controller. One way to achieve this is probably to use different naming for controllers: related SO answer

  2. Otherwise, you could put the cancel function on the $scope variable in createOrEditPropertyModal.

Just change createOrEditPropertyModal.js:

vm.cancel = function () {
    $uibModalInstance.close();
};

to

$scope.cancel = function () {
    $uibModalInstance.close();
};
  1. You can pass functions to modals similar to directives: related SO answer
Community
  • 1
  • 1
fodma1
  • 3,485
  • 1
  • 29
  • 49
  • The second solution might not work because http://stackoverflow.com/questions/23780181/angular-ui-modal-can-not-refer-to-parent-scope. Please let me know, and I'll update my answer – fodma1 Jul 24 '16 at 08:35
  • Can you tell me little bit more about the 2nd option ? May be simple code snippet. – Sampath Jul 24 '16 at 08:36
  • Yes,Now it is working.Thanks for that.But I think this is not a good way to handle parent/child reference no ? What is your thoughts ? If I change the different names for the controllers then I think I have to change all the UI components names also no ? Which method do you think is better when we consider the maintainability and etc ? – Sampath Jul 24 '16 at 08:52
  • @Sampath I don't know if you tried, but I'd prefer the third one if you can pass the cancel function by the time of instantiation. Using the named controllers is probably not a good idea, as it prevents reusability, same for accessing the parent. Which one worked btw? If one of them is not working I'd rather delete it. – fodma1 Jul 24 '16 at 08:58
  • Your 3rd solution may be worked for this situation.But how can I share the data between controllers ? Let's say I need to use the parent ctrl's `propertId` within my child ctrl. Then how can I do that ? Again I have to face the same issue no ? – Sampath Jul 24 '16 at 09:21
  • I think the cleanest way is to use directives (think of component architecture) and pass data in `bindToController`. https://toddmotto.com/no-scope-soup-bind-to-controller-angularjs/. It's like a defined interface, so it removes the implicitness – fodma1 Jul 24 '16 at 09:33
  • Thanks a lot for your invaluable suggestions. +1 :) – Sampath Jul 24 '16 at 10:17
1

You can do vm.cancel() directly inside a child form as you are already using controllerAs pattern. But in your case you have both controller alias as vm it is referring to current child controller context. Changing name of either of controller alias would make it working.

Best way to solve this issue would change your controller alias to different name. Controller aaliases should be like by looking at their name's you can pretend which controller it is.

--

The ng-click isn't working because cancel method isn't there inside $parent scope. You should be doing $parent.vm.cancel(). But I'd not prefer you to use $parent on view, because bad practice.

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • Actually my set up is like that.I have updated the question.Please see that.But that `cancel()` method is not being fired.Is that due to same name for the controllers ? I mean about the `vm` – Sampath Jul 24 '16 at 08:41
  • Might be.. do try changing the name.. on view it must work – Pankaj Parkar Jul 24 '16 at 08:43
  • It's because your controller `propertyForm as vm` is shadowing `createOrEditPropertyModal as vm`. – fodma1 Jul 24 '16 at 08:43
  • Yes,now your 2nd option is working.Thanks for that.But can you tell me a best way to refactor this ? – Sampath Jul 24 '16 at 08:55
  • Best way is to have different controller alias on view, inspite of having `vm` have some name which can describe which controller it is. – Pankaj Parkar Jul 24 '16 at 09:14
  • Hope I have to change the UI elements with the new alias name and no need to change anything within the controller no ? – Sampath Jul 24 '16 at 09:26
  • I don't understand you last statement, if you don't wanted to changes in code? Why you are asking for best practices suggestions then? – Pankaj Parkar Jul 24 '16 at 09:41
  • Nope, I would like to do the code changes.This is my question.Let's say I have given alias as `pm`.Then I need to change all the UI elements like this `ng-model="pm.property.priority"` and so on.But on that controller where I can keep like this no `var vm = this; vm.saving = false; vm.property = { id: null };` Am I wrong ? – Sampath Jul 24 '16 at 09:52
  • 1
    No need to change controller code.. inside a controller `var vm` is just a variable name which holds reference of `this`, you need to changeview bindings only. That's it. Apologies, for my misunderstanding. ;) – Pankaj Parkar Jul 24 '16 at 09:53