admin管理员组

文章数量:1307050

I need to track when a user changes the state of a checkbox in Ionic, save it to localStorage, and then use it to load again later - so it remembers their settings.

My toggle code looks like this:

<li class="item item-toggle">
     National Insurance {{ni_toggle}}
     <label class="toggle toggle-positive">
       <input type="checkbox" ng-model="ni_toggle" ng-click="updateLocalStorage()" id="has_national_insurance" name="has_national_insurance">
       <div class="track">
         <div class="handle"></div>
       </div>
     </label>
  </li>

And in my controller I have:

angular.module('starter.controllers', [])

.controller('SettingsCtrl', function($scope, $ionicPlatform) {
    $ionicPlatform.ready(function() {
    // Ready functions

    });

 $scope.updateLocalStorage = function() {

    window.localStorage.setItem( 'has_national_insurance', $scope.ni_toggle );
    console.log( $scope.ni_toggle );

}

})

However, it logs out to the console as undefined. If I explicitly set $scope.ni_toggle = false; it will log false and won't update to true when I toggle the checkbox to on.

EDIT:

app.js:

// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])

  .run(function($ionicPlatform) {
    $ionicPlatform.ready(function() {
      // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
      // for form inputs)
      if(window.cordova && window.cordova.plugins.Keyboard) {
        cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      }
      if(window.StatusBar) {
        // org.apache.cordova.statusbar required
        StatusBar.styleDefault();
      }

    });
  })



.config(function($stateProvider, $urlRouterProvider) {

  // Ionic uses AngularUI Router which uses the concept of states
  // Learn more here: 
  // Set up the various states which the app can be in.
  // Each state's controller can be found in controllers.js
  $stateProvider

    // setup an abstract state for the tabs directive
    .state('tab', {
      url: "/tab",
      abstract: true,
      templateUrl: "templates/tabs.html"
    })

    // Each tab has its own nav history stack:

    .state('tab.dash', {
      url: '/dash',
      views: {
        'tab-dash': {
          templateUrl: 'templates/tab-dash.html',
          controller: 'DashCtrl'
        }
      }
    })

    .state('tab.settings', {
      url: '/settings',
      views: {
        'tab-settings': {
          templateUrl: 'templates/tab-settings.html',
          controller: 'SettingsCtrl'
        }
      }
    })

    .state('tab.info', {
      url: '/info',
      views: {
        'tab-info': {
          templateUrl: 'templates/tab-info.html',
          controller: 'InfoCtrl'
        }
      }
    })

        .state('tab.about', {
      url: '/about',
      views: {
        'tab-about': {
          templateUrl: 'templates/tab-about.html',
          controller: 'AboutCtrl'
        }
      }
    })

  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/tab/dash');

});

controllers.js:

angular.module('starter.controllers', [])

.controller('DashCtrl', function($scope) {
})

.controller('SettingsCtrl', function($scope, $window, $ionicPlatform) {
    $ionicPlatform.ready(function() {

    });

    $scope.ni_toggle = $window.localStorage.getItem('has_national_insurance') === "true";

    $scope.updateLocalStorage = function() {
            $window.localStorage.setItem( 'has_national_insurance', $scope.ni_toggle );
            console.log( $scope.ni_toggle );
        }   


})

.controller('InfoCtrl', function($scope) {
})

.controller('AboutCtrl', function($scope) {
});

templates/tab-settings.html:

<li class="item item-toggle">
     National Insurance {{ni_toggle}}
     <label class="toggle toggle-positive">
       <input type="checkbox" ng-model="ni_toggle" ng-change="updateLocalStorage()" id="has_national_insurance" name="has_national_insurance">
       <div class="track">
         <div class="handle"></div>
       </div>
     </label>
  </li>

Working example of the problem

I need to track when a user changes the state of a checkbox in Ionic, save it to localStorage, and then use it to load again later - so it remembers their settings.

My toggle code looks like this:

<li class="item item-toggle">
     National Insurance {{ni_toggle}}
     <label class="toggle toggle-positive">
       <input type="checkbox" ng-model="ni_toggle" ng-click="updateLocalStorage()" id="has_national_insurance" name="has_national_insurance">
       <div class="track">
         <div class="handle"></div>
       </div>
     </label>
  </li>

And in my controller I have:

angular.module('starter.controllers', [])

.controller('SettingsCtrl', function($scope, $ionicPlatform) {
    $ionicPlatform.ready(function() {
    // Ready functions

    });

 $scope.updateLocalStorage = function() {

    window.localStorage.setItem( 'has_national_insurance', $scope.ni_toggle );
    console.log( $scope.ni_toggle );

}

})

However, it logs out to the console as undefined. If I explicitly set $scope.ni_toggle = false; it will log false and won't update to true when I toggle the checkbox to on.

EDIT:

app.js:

// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])

  .run(function($ionicPlatform) {
    $ionicPlatform.ready(function() {
      // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
      // for form inputs)
      if(window.cordova && window.cordova.plugins.Keyboard) {
        cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      }
      if(window.StatusBar) {
        // org.apache.cordova.statusbar required
        StatusBar.styleDefault();
      }

    });
  })



.config(function($stateProvider, $urlRouterProvider) {

  // Ionic uses AngularUI Router which uses the concept of states
  // Learn more here: https://github./angular-ui/ui-router
  // Set up the various states which the app can be in.
  // Each state's controller can be found in controllers.js
  $stateProvider

    // setup an abstract state for the tabs directive
    .state('tab', {
      url: "/tab",
      abstract: true,
      templateUrl: "templates/tabs.html"
    })

    // Each tab has its own nav history stack:

    .state('tab.dash', {
      url: '/dash',
      views: {
        'tab-dash': {
          templateUrl: 'templates/tab-dash.html',
          controller: 'DashCtrl'
        }
      }
    })

    .state('tab.settings', {
      url: '/settings',
      views: {
        'tab-settings': {
          templateUrl: 'templates/tab-settings.html',
          controller: 'SettingsCtrl'
        }
      }
    })

    .state('tab.info', {
      url: '/info',
      views: {
        'tab-info': {
          templateUrl: 'templates/tab-info.html',
          controller: 'InfoCtrl'
        }
      }
    })

        .state('tab.about', {
      url: '/about',
      views: {
        'tab-about': {
          templateUrl: 'templates/tab-about.html',
          controller: 'AboutCtrl'
        }
      }
    })

  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/tab/dash');

});

controllers.js:

angular.module('starter.controllers', [])

.controller('DashCtrl', function($scope) {
})

.controller('SettingsCtrl', function($scope, $window, $ionicPlatform) {
    $ionicPlatform.ready(function() {

    });

    $scope.ni_toggle = $window.localStorage.getItem('has_national_insurance') === "true";

    $scope.updateLocalStorage = function() {
            $window.localStorage.setItem( 'has_national_insurance', $scope.ni_toggle );
            console.log( $scope.ni_toggle );
        }   


})

.controller('InfoCtrl', function($scope) {
})

.controller('AboutCtrl', function($scope) {
});

templates/tab-settings.html:

<li class="item item-toggle">
     National Insurance {{ni_toggle}}
     <label class="toggle toggle-positive">
       <input type="checkbox" ng-model="ni_toggle" ng-change="updateLocalStorage()" id="has_national_insurance" name="has_national_insurance">
       <div class="track">
         <div class="handle"></div>
       </div>
     </label>
  </li>

Working example of the problem

Share Improve this question edited Aug 1, 2014 at 16:00 Ian asked Aug 1, 2014 at 12:24 IanIan 8655 gold badges18 silver badges30 bronze badges 3
  • Can i see the entire controller? I need more context. – pattmorter Commented Aug 1, 2014 at 12:30
  • That's all I have in the SettingsCtrl right now. Updated above ^ – Ian Commented Aug 1, 2014 at 12:54
  • You're problem is that $scope.ni_toggle isn't defined. Might seem "well duh" but if you look in your controller you have nothing that says $scope.ni_toggle = blah blah blah which is a dead giveaway for me. – pattmorter Commented Aug 1, 2014 at 12:59
Add a ment  | 

3 Answers 3

Reset to default 5

I am not familiar with Ionic's oddities (if there are any), but from a general JS perspective there seem to be a few issues with your code.

  1. You are not initializing ni_toggle.

  2. You are using ngClick which will get fired before the model has been updated by the ngModel directive.
    You should use ngChange instead.

  3. In Angular, you should use $window instead of window (it doesn't hurt and it can prove useful in many cases (e.g. testing)).

  4. Note that localStorage can only store strings (not booleans). So, even if you pass false, it will be stored as 'false', which is equivalent to true when cast to boolean.


Taking the above into account, your code should look like this:

<input type="checkbox" ng-model="ni_toggle" ng-change="updateLocalStorage()" ... />

.controller('SettingsCtrl', function($scope, $window, $ionicPlatform) {
    $ionicPlatform.ready(function() {
        // Ready functions
    });

    $scope.ni_toggle = $window.localStorage.getItem('has_national_insurance') === 'true';
    $scope.updateLocalStorage = function () {
        $window.localStorage.setItem('has_national_insurance', $scope.ni_toggle);
        console.log($scope.ni_toggle);
    };
});

See, also, this short demo.

I ran into a similar situation for displaying user information a while ago with my ionic app. I don't have my original source code in front of me but I'm pretty sure this is how you need to do it.

angular.module('starter.controllers', [])

    .controller('SettingsCtrl', function($scope, $ionicPlatform) {

        this.toggle = true; // make sure its defined somewhere

        $scope.ni_toggle = function() {
            return this.toggle;
        }

        $scope.updateLocalStorage = function() {
            window.localStorage.setItem(
                'has_national_insureance',
                $scope.ni_toggle
            );
            console.log($scope.ni_toggle);
        }

    });

Hope this gets you going in the right direction.

EDIT See ExpertSystem's answer. He answered it way better than I could.

No need of any function definition in controller

 <script>
 angular.module('checkboxExample', [])
.controller('ExampleController', ['$scope', function($scope) {
  $scope.checkboxModel = {
   value1 : true,
   value2 : 'YES'
 };
}]);

<form name="myForm" ng-controller="ExampleController">
<label>Value1:
<input type="checkbox" ng-model="checkboxModel.value1">
</label><br/>
<label>Value2:
<input type="checkbox" ng-model="checkboxModel.value2"
       ng-true-value="'YES'" ng-false-value="'NO'">
</label><br/>
<tt>value1 = {{checkboxModel.value1}}</tt><br/>
<tt>value2 = {{checkboxModel.value2}}</tt><br/>

本文标签: javascriptGet and set a checkbox in Ionic Framework (AngularJS)Stack Overflow