2

Why is $scope.Templt_Kind_ID not changing after the bootstrap popup is closed? Note: I do not close the popup until I retrieve the dropdown value from the popup.

I call a bootstrap popup with edit controls. After a user changes a dropdown value, it calls the $scope.onSelectChangeTemplate_kind = function () In the function below,

var ddlID = $scope.selectedCountry; contains the correct value.
$scope.Templt_Kind_ID = ddlID;  // << $scope.Templt_Kind_ID = 34 as it should be

Upon closing the popup, I expected $scope.Templt_Kind_ID = 34 but it contains -1 which is what it was first initialized to.

Why? $scope.Templt_Kind_ID should = 34

JavaScript

app.controller('APIController',  function ($scope, $window, $element, $log, $http, APIService) {
    $scope.Templt_Kind_ID = -1; // << Initial value

// Bootstrap popup. After dropdown in bootstrap is changed, this is called.
// I tried a number of things including $scope.onSelectChangeTemplate_kind = function ($scope) 
$scope.onSelectChangeTemplate_kind = function () {
    var ddlID = $scope.selectedCountry; // << contains correct value
    $scope.Templt_Kind_ID = ddlID;  // << $scope.Templt_Kind_ID = 34 as it should be
}

// Bootstrap popup is closed.
// Why is $scope.Templt_Kind_ID=-1 although it shuold be 34 ?????
// Why is $scope.Templt_Kind_ID=-1 although it shuold be 34 ?????
$scope.hide = function () {
        console.log('model one hidden Templt_Kind_ID=' + 
 $scope.Templt_Kind_ID); // <<<<<<
         // << $scope.Templt_Kind_ID is still -1 although it shuold be 34 
        $scope.showModal1 = false;
}
}) 

<html>
<modal-body>
    <div ng-controller="APIController">
        <select id="ddlSelectedCountry" ng-model="selectedCountry"  ng-change="onSelectChangeTemplate_kind()">
            @*3-SP Insert*@
            <option value="">Select Account</option>
            <option 
                    ng-model="selectedCountry"
                    ng-repeat="item in list_Template_kind" value="{{item.Templt_Kind_ID}}"

                    >
                {{item.Templt_Kind_ID}}-{{item.Templt_Kind_Name}}
            </option>
        </select>
    </div>
</modal-body>
</html>
Alon Eitan
  • 11,997
  • 8
  • 49
  • 58
JenniferWalters
  • 87
  • 1
  • 11
  • Why do you have `ng-model="selectedCountry"` on the `option`s of the select? – Alon Eitan Apr 12 '17 at 14:34
  • And what do you see when you add `console.log('model one hidden Templt_Kind_ID=' + $scope.selectedCountry);` in the `hide()` function? – Alon Eitan Apr 12 '17 at 14:38
  • >>Why do you have ng-model="selectedCountry" on the options of the select? I hate to say, but I have been working on this for a day and a half and do not remember why I put it in there. >>And what do you see when you add console.log('model one hidden Templt_Kind_ID=' + $scope.selectedCountry); -1 – JenniferWalters Apr 12 '17 at 14:41
  • Well I don't know how or from where you call the `hide()` function, but there is an implementation of the bootstrap components for angular, you might want to try the native modal - http://angular-ui.github.io/bootstrap/#!#modal it should probably solve your issue – Alon Eitan Apr 12 '17 at 14:47
  • I call the hide() function from a button in the modal popup – JenniferWalters Apr 12 '17 at 14:50
  • >> try the native modal - angular-ui.github.io/bootstrap/#!#modal I asked about that awhile ago and was told not to use it because we are already using bootstrap ui. – JenniferWalters Apr 12 '17 at 15:00

1 Answers1

0

As I recommended in the comments, you can use the native angular module.

Here you open the modal and select the template, when you click OK the modal return the selected template back to the controller:

var app = angular.module('app', ['ui.bootstrap']);

app.controller('ctrl', ['$scope', '$uibModal', '$log', function($scope, $uibModal, $log) {
  // function to open the Modal from the view, the function accept "selection" argument that will be sent to the model's controller 
  $scope.openModal = function (selection) {
    var modalInstance = $uibModal.open({
      templateUrl: 'modal.html',
      resolve: {
          // Pass a pre selection template to the Model's controller (pass null if you don't want to pre select)
          selection: function() { return selection; }
      },
      controller: function($scope, $uibModalInstance, selection) {
           // save the preselected template and display it on the model's select box 
           $scope.selectedTemplate = selection;

           // Mock of the actual list of templates
           $scope.list_Template_kind = [
                { Templt_Kind_ID: 1, Templt_Kind_Name: 'Template 1' },
                { Templt_Kind_ID: 2, Templt_Kind_Name: 'Template 2' },
                { Templt_Kind_ID: 3, Templt_Kind_Name: 'Template 3' },
                { Templt_Kind_ID: 4, Templt_Kind_Name: 'Template 4' }
           ];

           // OK button was clicked
           $scope.ok = function () {
               // Send the selected template back to the main controller
               $uibModalInstance.close($scope.selectedTemplate);
           };

           // CANCEL button was clicked
           $scope.cancel = function () {
               $uibModalInstance.dismiss('cancel');
           };
       }
    });

    // The "$uibModal.open()" returns a promise that resolves when called "$uibModalInstance.close()" from the model's controller
    // or rejected when you call  "$uibModalInstance.dismiss()".
    // You can pass any value to those promise functions from the Model controller and use it in the resolve/reject callbacks 
    modalInstance.result.then(function (selectedItem) {
      // Get the selected template sent back from the modal ($uibModalInstance.close($scope.selectedTemplate);)
      $scope.selected = selectedItem;
    }, function () {
      // The user clicked on the "cancel" button
      $log.info('modal-component dismissed at: ' + new Date());
    });
  }
    
 }]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.min.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

<div ng-app="app" ng-controller="ctrl">
    <script type="text/ng-template" id="modal.html">
        <div class="modal-header">
            <h3 class="modal-title">The modal!</h3>
        </div>
        <div class="modal-body">
            <select id="selectedTemplate" ng-model="selectedTemplate"  ng-change="onSelectChangeTemplate_kind()">
                 <option value="">Select Account</option>
                 <option ng-repeat="item in list_Template_kind" value="{{item.Templt_Kind_ID}}">
                      {{item.Templt_Kind_ID}}-{{item.Templt_Kind_Name}}
                 </option>
            </select>
        </div>
        <div class="modal-footer">
            <button class="btn btn-primary" type="button" ng-click="ok()">OK</button>
            <button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
        </div>
    </script>
    
    <! -- Call "openModal" and pass "null" so no pre selection is displayed in the modal --> 
    <button ng-click="openModal(null)">Open</button>
    <! -- Call "openModal" and pass "2" so "Template 2" will be preselected in the modal -->
    <button ng-click="openModal('2')">Open (Preselect 2)</button>
    <! -- Call "openModal" and pass the {{ selected }} property so the last template selected since you last closed the modal will be shown in the modal -->
    <button ng-click="openModal(selected )">Open (Preselect last selected)</button>

     <! -- Show the last selected template in the view (For debugging purposes) -->
    <span ng-if="selected">{{ 'selected - ' + selected }}</span>
</div>
Alon Eitan
  • 11,997
  • 8
  • 49
  • 58
  • I am going to press the issue of angular-ui-bootstrap because it seems there are 2 $scope levels when using native bootstrap. Hey, after a day and a half, what is another day. Thanks Alon. – JenniferWalters Apr 12 '17 at 16:14
  • What do you mean by _press the issue of angular-ui-bootstrap_? If you can demonstrate the issue of the 2 level scope then I might be able to help, but as you can see from my answer - Using a native solution allows you to implement your requirements easily without having to handle the inner scope level (Well, at least with the details provided in your original question). – Alon Eitan Apr 12 '17 at 16:21
  • The 2 level scope comes from $scope.Templt_Kind_ID = ddlID not actually = 34 AFTER the modal closes. var ddlID = $scope.selectedCountry; // << contains correct value $scope.Templt_Kind_ID = ddlID; // << $scope.Templt_Kind_ID = 34 as it should be $scope.Templt_Kind_ID is not giving me an error, it just reverts to its original = -1 . So I say "2 level scope" because it reverts to -1 eventhough it is set to = 34 upon close. scope.Templt_Kind_ID = ddlID seems to be going somewhere else. – JenniferWalters Apr 12 '17 at 18:05
  • saw ONE post about this. (I wish I saw it yesturday.) http://stackoverflow.com/questions/21259127/returning-a-value-from-a-modal-in-angular-bootstrap As for "What do you mean by press the issue of angular-ui-bootstrap?": I asked about this awhile ago but I was told to keep using regular bootstrap ui since we were already using it. I totally disagreed but I am not the boss. I am going to create (on my own time) your recommendation on angular-ui-bootstrap . Maybe if they see your answer in action it will be approved. Your code is much more elegent. – JenniferWalters Apr 12 '17 at 18:06
  • 1
    I did discover a work-around with app.factory('factEdit', function () { return { selectedCountry: '' }; }); I think your solution is the correct solution... use the native library and will mark yours as solved. Tommorow, I will post my work around though in case it will help someone else. And shalom for you. Thanks very much. – JenniferWalters Apr 12 '17 at 18:06
  • 1
    I ran into another problem with the AngularJS validation and closing the popup after the SAVE button is clicked. Finding workarounds for the implementation I was told to work with is just too costly. Alon was correct. Using angular-ui-bootstrap instead of Bootstrap UI is the correct way to implement the code. Thanks Alon. – JenniferWalters Apr 15 '17 at 13:20
  • YAY! Glad to help @JenniferWalters – Alon Eitan Apr 15 '17 at 13:22