ionic-frameworkangular-ngmodelionic-popup

How to remember Ionic Range slider position $ionicPopup


I have directive to change font size on page:

.directive('textSizeSlider', ['$document', function ($document) {
    return {
      restrict: 'E',
      template: '<div class="range"><i class="icon" ng-style="{ fontSize: min + unit }">A-</i><input type="range" min="{{ min }}" max="{{ max }}" step="{{ step || 0 }}" ng-model="textSize" value="{{ value }}" /><i class="icon" ng-style="{ fontSize: max + unit }">A+</i></div>',
      scope: {
        min: '@',
        max: '@',
        unit: '@',
        value: '@',
        step: '@'
      },
      link: function (scope, element, attr) {
        scope.textSize = scope.value;
        scope.$watch('textSize', function (size) {
            var x = document.getElementsByTagName("P");
            var i;
            for (i = 0; i < x.length; i++) {
            x[i].style.fontSize = size + scope.unit;
            }
        });
      }
    }
  }]);

On my page by button click open Popup with range to decrease/increase font size. But every time when I open Popup range slider have default position sets in value in my controller. How to save changed value for Range? This is my function in controller:

  $scope.fontAdjust = function() {

    var alertPopup = $ionicPopup.alert({
    title: 'Font adjustment',
    template: '<text-size-slider min="10" max="18" unit="px" value="14" step="0"></text-size-slider>'
    })

   }

Solution

  • What's added in controller:

    1. Have a $scope.vm.fontSize variable in the controller and use it in your template like this

      template: '<text-size-slider min="10" max="18" unit="px" value="vm.fontSize" step="0"></text-size-slider>'
      

      You may read Understanding Scopes to know why I have used vm.fontSize and not primitive fontSize.

    2. Add a watch in controller to be notified of the changed value. Here the changed value can be saved somewhere e.g. in localStorage.

      $scope.$watch('vm.fontSize', function (newValue, oldValue) {
        console.log(newValue);
        localStorage.fontSize = newValue;
      });
      

    and then in your directive use the following code:

    return {
      restrict: 'E',
      template: '<div class="range"><i class="icon" ng-style="{ fontSize: min + unit }">A-</i><input type="range" min="{{ min }}" max="{{ max }}" step="{{ step || 0 }}" ng-model="value" /><i class="icon" ng-style="{ fontSize: max + unit }">A+</i></div>',
      scope: {
        min: '@',
        max: '@',
        unit: '@',
        value: '=',
        step: '@'
      },
      link: function (scope, element, attr) {
        scope.textSize = scope.value; // This is not required
        scope.$watch('value', function (size) {
          var x = document.getElementsByTagName("P");
          var i;
          for (i = 0; i < x.length; i++) {
            x[i].style.fontSize = size + scope.unit;
          }
        });
      }
    }
    

    What's changed in directive:

    1. value: '@' to value: '='. This to use the same reference in outer scope then to create a local one in the directive scope. Read More.
    2. In template property, added ng-model="value" to bind the value (from outer scope) directly to the ng-model and removed the value attribute as ng-model updates it automatically and is unnecessary.
    3. Added watch on the value directly than on textSize which makes it unnecessary.

    When controller is loaded, you may read localStorage.fontSize and assign it to $scope.vm.fontSize and save it back in localStorage.fontSize whenever its value is changed.