I have a label with an input box like so:
<label class="item item-input">
<input type="text" data-ng-model="description"
placeholder="Add a Description!">
</label>
As you can see this input box is binded to the scope "description"
In my controller I have something along the lines of this:
$scope.description = "";
$scope.submit = function() {
console.log($scope.description);
};
In my HTML I also have this line:
<div ng-show="description.length <= maxChars">{{description}}</div>
The submit function is called when the user hits the submit button after typing inside the input box. The description displays correctly. As the user types into the input box the description gets updated in the HTML but NOT in the controller.
I have a feeling it has something to do with setting description to an empty string but it is clearly getting updated as far as the HTML is concerned. But it keeps console.logging and empty string regardless.
In order to get this to work I had to pass description directly into the submit function (And also update the function accordingly):
<button class="button button-positive" data-ng-click="submit(description)">Submit</button>
This is completely unnecessary since Angular should be doing Two-way data binding automatically but it's not.
Anyone have any ideas?
Any help would be appreciated.
EDIT:
Here is the full HTML due to popular demand.
<ion-view title="Moments" id="page2">
<ion-content padding="true" class="has-header">
<img src="{{picture}}" height="300px" width="100%"> </img>
<div class="row">
<div ng-show="description.length > maxChars" style= "color: red">{{description}}</div>
<div ng-show="description.length <= maxChars">{{description}}</div>
</div>
<div class="row" ng-if="description">
<div ng-show="description.length > maxChars" style= "color: red">{{description.length}} / {{maxChars}}</div>
<div ng-show="description.length <= maxChars" style= "color: green">{{description.length}} / {{maxChars}}</div>
</div>
<div class="row">
<div class="col">
<label class="item item-input">
<input type="text" data-ng-model="description" placeholder="Add a Description!">
</label>
</div>
<button style="margin-right: 5px" class="col col-10 button button-positive" data-ng-click="checkDescription(description)">OK</button>
</div>
<div class="row">
<div class="col"><ion-checkbox data-ng-change="changeLocation()" data-ng-model="location">Show Location</ion-checkbox></div>
</div>
<div class="row">
<div class="button-bar">
<button class="button button-assertive" data-ng-click="cancel()">Cancel</button>
<button class="button button-positive" data-ng-click="submit(description)">Submit</button>
</div>
</div>
</ion-content>
</ion-view>
I am also aware that in this question the submit function takes no parameters. That's how I would like it to be. Currently my submit button takes one parameter(the description). This should not be nessesary. I am having the same problem with the function 'checkDescription' as well. That function should also have no parameters but again, I am forced to pass the description directly into the function. Something I prefer not to do.
Executive Summary:
In AngularJS, a child scope normally prototypically inherits from its parent scope. One exception to this rule is a directive that uses
scope: { ... }
-- this creates an "isolate" scope that does not prototypically inherit.(and directive with transclusion) This construct is often used when creating a "reusable component" directive. In directives, the parent scope is used directly by default, which means that whatever you change in your directive that comes from the parent scope will also change in the parent scope. If you setscope:true
(instead of scope:{ ... }
), then prototypical inheritance will be used for that directive.Scope inheritance is normally straightforward, and you often don't even need to know it is happening... until you try 2-way data binding (i.e., form elements, ng-model) to a primitive (e.g., number, string, boolean) defined on the parent scope from inside the child scope. It doesn't work the way most people expect it should work. What happens is that the child scope gets its own property that hides/shadows the parent property of the same name. This is not something AngularJS is doing – this is how JavaScript prototypal inheritance works. New AngularJS developers often do not realize that
ng-repeat
,ng-switch
,ng-view
,ng-include
andng-if
all create new child scopes, so the problem often shows up when these directives are involved. (See this example for a quick illustration of the problem.)This issue with primitives can be easily avoided by following the "best practice" of always have a dot '.' in your ng-models – watch 3 minutes worth. Misko demonstrates the primitive binding issue with ng-switch.
--AngularJS Wiki -- The Nuances of Scope Prototypal Inheritance
I tried to do the '.' notation in my scope but whenever I try to reference it like this:
$scope.moment.description = "";
It says "Cannot read property 'description' of
undefined
.
The code needs to create the object before assigning a value to a property:
$scope.moment = {};
$scope.moment.description = "";
//OR
$scope.moment = { description: "" };