angularjs - ng-switch does not bind ng-model
Asked Answered
U

3

47

I have this repro http://embed.plnkr.co/nVCmukG5abpi1Y4ZHkrq that show when I click 'Title3' and enter a value in text box although the entered value shows reflected in the UI, when I click the 'click' button nothing is binded for the scope attribute $scope.test.

I don't know what is wrong with ng-switch or maybe I'm doing something wrong. Help is appreciated!!!

http://embed.plnkr.co/nVCmukG5abpi1Y4ZHkrq

Unific answered 23/3, 2013 at 23:30 Comment(0)
A
89

This is a scope inheritance problem due to ng-switch creating its own scope.

One recommendation made often is always to use a dot on models. The reason is that when the controller scope item is an object and not a primitive, sub scopes will create a reference to the initial object. If model is a primitive it will not update the original.

For example:

<input ng-model="test.value" placeholder="pre" type="text" />
$scope.test={value:''}

Another approach is to use $parent in html model markup:

<input ng-model="$parent.test" placeholder="pre" type="text" />

Using the dot methodology is a good practice to avoid these issues as you don't need to think about deeper nested scopes.

Demo using test.value as model: http://plnkr.co/edit/CkiF55bLXsYzR6ZjcrJp?p=preview

Reference regarding dot in models(valuable reading): https://github.com/angular/angular.js/wiki/Understanding-Scopes

Ailsa answered 24/3, 2013 at 0:21 Comment(1)
Any reason for this behavior? I just spent three hours trying to figure it out because I changed manual showing/hiding of my two views of the same data into an ng-switch 3 days and 3 source control revisions ago and everything seemed to work fine. I have a select that sets the current character for what is selected in a list and that character has a lists of tasks. Everything looks find, but when I click on the buttons on my tasks it is using the original parent character. Any way to access the child scope in a click method (I'm using executeTask($index))?Forespent
H
10

This is because you're actually creating a child scope inside of the ng-switch. So another test property exists on a scope belonging to the ngSwitch directive. It will initially show the value from it's parent scope, but when you edit it, because it is a primitive, it only edits the value on the child, not the parent. Prototypical inheritance does not come into play here (but that's what we need).

When you click the button the button is alerting/console.logging the property on the parent scope... which the child cannot change.

To fix this use $parent.test on your ng-model attribute in your ngSwitch:

a snippet:

<span class="pew"  ng-switch-when="title2">
  <input ng-model="$parent.test" placeholder="pre" type="text" />
  {{test}}
</span>

And here's a fork of your plunker showing it in action.

Hardnosed answered 24/3, 2013 at 0:18 Comment(0)
T
4

I've encountered similar issue, and I've solved by creating a scope variable in the controller and used that with in ng-include and ng-switch. This way if you've deep nested ng-include's with in ng-switch and it goes on, we can still directly use that scope variable.

As all child scopes (here, ng-include/ng-switch) extends from parent scope (generally, controllers scope), we can access parent scope directly from with in these child scopes without a problem.

Using $parent will require to write like $parent.$parent.$parent.someProp

Example Plunk: http://plnkr.co/edit/8UGH7nUpFmATiXfkYSwr?p=preview

Tantivy answered 8/5, 2013 at 5:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.