EDIT: I felt mean with my previous response, since it was basically "You're wrong, do it my way", so here is an explanation of the problem.
You have a div with ng-ctrl
set on it. This div now has a scope with an instance of myCtrl
.
ng-include
creates a child scope, which inherits from its parent scope (the previously created myCtrl
scope). This scope will not have direct references to selectedCountry or countries, but angular will automatically search parent scopes for values when it doesn't find them. This is important. (This is how JavaScript prototypical inheritance works. More info here.)
You also have an ng-view
, which in your route provider you've told has its controller set to myCtrl. This means it is going to create a seperate myCtrl
scope, which is also a child of the outer myCtrl
scope. Because it is a child of the outer myCtrl
scope, like your ng-include
scope, angular would usually search its parent for properties it can't find on the immediate scope.
However this is where it gets complicated. In this case, because it is also another instance of myCtrl
, it created new properties for selectedCountry
and countries
on itself and thus does not need to search its parent for the properties when you reference them. Angular matches objects by reference, and not by a deep object comparison, therefore these objects are considered to be different and selecting something from list A changes selectedCountry
to a reference of an object which doesn't exist on list B.
This is why you were forced to use $parent
, to try and point to the same references as the scope outside it, which your ng-include
is automatically referencing through its parent.
The second problem with your code, is whilst you used $parent
for the selectedCountry
value, you did not use $parent
for the countries
array, and so it is using the array of objects that were re-created on the child myCtrl
to fill your select box. Again, even though the objects have the same values, angular compares by reference for ng-options
. So the Modor
on select A is not the same as Modor
on select B.
As an additional note, there is a third problem you could have created had you not set $parent
on selectedCountry
for menu.html and checkout.html. Whilst initially it would search the parent for selectedCountry
, if you changed the select, it would create a property on the child scope instead of bubbling up to the parent, and thus from then on it would no longer match the parent's version of selectedCountry
.
So, to summise, the way you've coded it you have two choices.
The crap choice:
$parent.everything
- Here is a Plunkr of
$parent
fixing everything (please don't do this)
The responsible choice:
- Use
controllerAs
to prevent scoping problems forever
- Here is a Plunkr of how I would do it with
controllerAs
A short guide for controllerAs
is here
TL;DR; if you don't want to read guide
- In your html ->
ng-controller="myCtrl as myCtrl"
- Also in your html ->
myCtrl.countries
- If it was a route/directive, set this property ->
controllerAs: 'myCtrl'
- In your Controller, instead of
$scope.stuff
-> this.stuff
- Note:
this
is for property/function assignment. If you're using a $scope
function like $watch
, that is still done on $scope
.
Just as an extra tip, this is my bible for coding in angular. Follow these guidelines and your code will be immaculate and prevent you from these kind of pitfalls.