Problem with ion-content and scope vars inside function

Hi,

scope variables are undefined inside controller function if input field with ng-model is inside ion-content.

If I place the same input field outside ion-content, everything works as expected.

I think I maybe missing something because if I recall properly several versions back that worked as it should.

Please help.

Thanks

1 Like

I’m guessing it’s because you aren’t using “dot notations”.

$scope.volume = 5

You need to use :

$scope.data = { 'volume' : 5}

Definitive Resource : https://github.com/angular/angular.js/wiki/Understanding-Scopes

Thank you for your answer. But I’m still a bit confused, and probably wasn’t clear enough. Here is the simple code that worked for me quite nice until put into ion-content directive.
In the controller:

$scope.clickMe = function(){
     console.log( $scope.someVar );
};

And in the ion-content:

<input type="text" ng-model="someVar" />
<button class="button" ng-click="clickMe()">Click</button>
{{someVar}}

Now what’s interesting is that writing in a field immediately binds on screen, but clicking on a button yields
undefined in a console.
Further, what’s confusing me is that this behavior manifests only if input field is inside ion-content directive, but if you put everything out, even in a sub-header for example, it works quite as I expected.

I’m relatively new to whole angular + ui-router + ionic stack so please bare with me, but this is really confusing.
I still have a feeling that I’m missing something, but I’m not sure because it behaves differently in different view directives.

Thank you for your patience,

Igor

The problem is specific with ion-content because of the way this directive is defined in the Ionic source code. It specifically creates it’s own child scope.

.directive('ionContent', [
  '$parse',
  '$timeout',
  '$ionicScrollDelegate',
  '$controller',
  '$ionicBind',
function($parse, $timeout, $ionicScrollDelegate, $controller, $ionicBind) {
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    require: '^?ionNavView',
    scope: true,
    template:
    '<div class="scroll-content">' +
      '<div class="scroll"></div>' +
    '</div>',

Because of this and the way inheritance works in JavaScript, you cannot use 2 way binding. Basically your $scope.clickMe is defined in you controller and is just created as a new primitive to the scope of ion-content. It is not copied by reference like an object would be.

Reread that article I linked to. It’s critical in understanding how this all works and overcoming these issues.

I wonder if there is a quick fix: Plunker - Untitled

    $scope.add = function(item) {
      alert("adding " + item + " but due to isolated scopes cannot clear search field");
      
      $scope.searchText = "";
    }

I have a list and search field sitting in ion-content and I would like to clear the filter after adding the item.

Possible?
(Thanks)

“dot notation” saves the day : http://plnkr.co/edit/2ZNeHRmYQ1cE3zWLpo2X?p=preview

Of course: http://www.youtube.com/watch?v=ZhfUv0spHCY&feature=share&t=30m51s

(Misko Hevery AngularJS Best Practices)

This is an old topic but still relevant.

I was able to get around the problem by binding my inputs to $parent.someModel.

So in the example above, changing the view to

<input type="text" ng-model="$parent.someVar" />
<button class="button" ng-click="clickMe()">Click</button>
{{someVar}}

Will allow you to properly bind the input box to the $scope from your controller as expected.

6 Likes

This worked perfectly and was all that was needed. Thanks!

hia thanks for your solution it saves my time so much

This fixed an issue on which i spent close to 3 hrs. Thanks a lot.