ng-focus doesn't work with ng-include - angularjs

I have a problem with ng-focus on ng-include elements. I use this part of code
<div ng-include="'template.tpl.html'" ng-controller="Ctrl"
ng-class="{'highlight':highlight==true,'nofocus':highlight==false}"></div>
and ng focus works fine when I have inside template.tpl.html regular DOM elements like:
<div class="form-group">
<label class="control-label">My label</label>
<div class="input-wrap">
<input type="text" name="Name" class="form-control"
ng-model="client.firstName" ng-disabled="displayMode != 'edit'"
ng-focus="highlight=true" ng-blur="highlight=false">
</div>
</div>
but, if I include another file in template.tpl.html it doesn't work anymore. For example if I apply in template.tpl.html the structure like below it won't work:
<div ng-include="'contacts/contacts-list.tpl.html'"></div>
Why ng-focus doesn't work on ng-include included in ng-include? Any tips on how to resolve this?

(Now that you have clarified your actual issue) As a continuation of the comment, ngInclude created a child scope of the provided scope, in your case child scope of child scope of Ctrl and well that does not matter since overall your wrapper is the Ctrl controller. But here you need to be careful while setting the scope property and expect the changes done from grandchild scope to be reflected in its grandparent scope. You have not even defined the properties in your controller, also even if you define them directly as scope.highlight = false the changes made to the property in the child or its child will not be reflected in the parent (though it will propagate down as a part of inheritance). You should remember scopes (except isolate scopes) are prototypically inherited, so in order to resolve this, you can use a property that holds the object reference which contains the property that needs to be modified, so that even if you change the value of property on that object from grandchild it will still reflect while accessing the same on the parent because they are all looking at the property on the same object reference
So in your controller initialize and object:-
.controller('MainCtrl', function($scope) {
$scope.settings = {};
});
Set the bindings accordingly in the main html:-
<div ng-include="'tmpl.html'" ng-controller="MainCtrl"
ng-class="{'highlight':settings.highlight,'nofocus':settings.highlight}"></div>
And in its grand child as well:-
<input type="text" name="Name" class="form-control"
ng-model="client.firstName"
ng-focus="settings.highlight=true" ng-blur="settings.highlight=false">
Plnkr
You wouldn't get a better explanation on angular scopes than this answer.

Related

Why the form does not get updated while the $scope does AngularJS

So I am having a form and when I load the form I call a function with it. The function fills the form with some data.
$scope.fill = function {
$scope.formData.name = 'Sara';
console.log($scope.formData.name);
})
And on the index view I have the following:
<div class="form-group">
<input type="text" class="form-control" name="name" ng-model="formData.name"></div>
So when I press the the button :
<button ng-controller="formController" ui-sref="front.form.profile" ng-click="fill()">Fill</button>
I want the form about the name to be filled with the value I defined.
The problem I have is that the $scope is updated, on console.log I get the name sara but the form is still empty and does not get updated>
I added $scope.apply() in the end of the function but it does not make any change .
Please help
ng-controller="formController" ui-sref="front.form.profile" ng-click="fill()"
Also you created children controller, also $scope is child scope, so that if you change value of child scope, the value of "$scope.formData.name" of parent's scope not changing.
you can using two-way binding via directive.
references: https://docs.angularjs.org/guide/directive
I hope that is helpful for you!
Your button has its own controller:
<button ng-controller="formController"
That creates a child scope for the button only. Remove it. You should also create the ui-sref attribute, since you wan't the button to fill the form, not to navigate to another state.

AngularJs multiple instances and nested controller

I got confused a bit about whether can we create multiple instance of controller and that to in nested form for eg -
<div ng-controller="abc">
<form ng-submit="call()">
<input type=text ng-model="content"/>
</form>
<div ng-controller = "abc">
<form ng-submit="call()">
<input type=text ng-model="content"/>
</form>
</div>
</div>
i just want to know that if i use the same model with other instance of controller, so model value would be same or different. Similar to static variable ?
i just want to know that if i use the same model with other instance
of controller, so model value would be same or different. Similar to
static variable ?
All declarations of ng-controller create a new instance of the controller. So, if you had two instances side by side, like this:
<div ng-controller="abc">
<input type=text ng-model="content"/>
</div>
<div ng-controller="abc">
<input type=text ng-model="content"/>
</div>
plunker
then, all of the $scope properties of each would be completely independent.
When a ng-controller is nested, then its scope inherits the parent controller's scope. So for this you'd expect that content refers to the same scope property:
<div ng-controller="abc">
<input type=text ng-model="content"/>
<div ng-controller="abc">
<input type=text ng-model="content"/>
</div>
</div>
plunker
However, since content is not defined directly in the controller something strange happens. If you fill in the parent input first. Both, inputs become bound to the same scope property. However, if you fill in the child input first, they are independent!
This can be confusing until you understand that Angular is being lazy when it creates the property on the scope. content is null at first on both scopes. It is only when it has a value that it will inherit.
So, what do you do if you want to keep things separate? Add an initial value to a $scope property inside the controller:
app.controller('abc', function($scope) {
$scope.content = '';
});
plunker
This way, each separate controller instance is initialized with its own content property.
Hope this helps.

Model not updated when view changes

I have a form for creating new records in a partial which I load in my main view like this
<div ng-controller="NewProductController">
<ng-include src=" 'views/partials/product-form.html' "></ng-include>
</div>
In the form, I have some input fields
..
<input ng-model="cip" type="text" id="cip" class="form-control" placeholder="Enter the CIP" autofocus="autofocus"/>
<input ng-model="name" type="text" id="name" class="form-control" placeholder="Enter the name" />
And in my controller, I'm sending a POST request with the values of the input fields:
...
.controller('NewProductController', function(Product, $scope) {
$scope.create = function () {
Product.create( {'cip': $scope.cip,
'name': $scope.name,
'dosage': $scope.dosage,
...
});
};
The problem is that when the values of the input fields change, it is not reflected in the controller ($scope.cip and $scope.name are undefined unless I initialized them with some value) but when $scope.cip and $scope.name are changed in the controller, the changes are correctly reflected in the view.
I thought that kind of updates are automatic or am I missing something ?
The reason why this is happening because ng-include creates a child scope. Since you are managing the model fields in the child scope i.e inside the template html, the fields are not available on the parent scope, where your controller is defined.
To fix this issue first and foremost thing that you need to do would be to create a obj such as product and define it on the controller NewProductController scope.
$scope.product={};
The template then should bind to sub properties of this product object.
<input ng-model="product.cip" type="text" id="cip" class="form-control" placeholder="Enter the CIP" autofocus="autofocus"/>
Now your changes would be available in the parent product object.
You can improve it a bit by passing the product object using ng-init like this
<ng-include src=" 'views/partials/product-form.html' " ng-init='model=product'></ng-include>
Now your template input fields change to
<input ng-model="cip" type="text" id="model.cip" class="form-control" placeholder="Enter the CIP" autofocus="autofocus"/>
Advantage
You template is not dependent on the structure of parent model class. Dependency is explicit. The template becomes more reusable as it clearly defines the model it works with, like in your case the template works with Product model.
For the sake of completeness of the answer i must link to this must read article, Understanding Scopes

How to prevent transcluding directive to create new child scope for the form directive?

I have a problem with directive transclude and the form directive. As you may know, the form will end up in the "scope" if you add the "name"-property to the form tag, then you can check for form validation and so on.
My problem start when i put the form tag in a directive that uses transclude. I'm aware of how to deal with this problem with two-way data binding, as mention here https://stackoverflow.com/a/14484903/1029874 -- "use an object instead of a primitive"
But my form ends up in the transcluding directives scope. Here is an example of what i want to do.
<div ng-controller="appCtrl">
<widget>
<widget-header>{{model.property}}</widget-header>
<widget-body>
<!-- The form will end up in "widget-body":s scope instead of appCtrl:s scope -->
<form name="appForm" ng-submit="submit()">
<input type="text" required ng-model="model.property" />
<input type="submit" value="submit" />
</form>
</widget-body>
</widget>
</div>
And here is the fiddle, http://jsfiddle.net/WLksJ/1/
Is there a way that I can get around this behavior?
Thanks!
An interesting question, but a problem that's easily avoided by using
<form name="appForm" ng-submit="submit(appForm.$valid)">
and checking the parameter in the submit function.
http://jsfiddle.net/udMJ7/
Another (perhaps better) option is to use this which is set to the scope of the last controller (in this case the form controller, which we want)
$scope.submit = function(){
if(this.appForm.$valid){
//post the form!!
}
};
http://jsfiddle.net/udMJ7/1/

AngularJS passing data from a directive controller to another

I have a form, which with you can edit an image gallery, of course I've created a directive for it, like this:
galleryEdit.html
<div>
<form ng-submit="submit()">
<label>Headline:</label>
<input type="text" ng-model="gallery.headline" placeholder="Enter headline here" value=""/>
<label>channels:</label>
<channelselect></channelselect>
<input type="submit"/>
</form>
</div>
So, galleryEdit has another directive channelSelect, which with you can select a channel (not only for galleries)
channelselect.html
<div>
<select>
<option value="{{channel.shortCode}}">{{channel.name}}</option>
</select>
</div>
GalleryEdit has a controller, that passes data (called "gallery") for its directive, so its $scope has $scope.gallery property, which contains channel id: $scope.gallery.channel.
Since channelselect has different controller, that has its scope, this gallery.channel cannot be seen from that scope.
Is there any way to pass data from gallery to channel controller/directive ?
Using $scope.$parent is not a solution, since channelSelect should not know anything where the data is coming from.
You can set up bi-directional binding between your galleryEdit directive's scope and your channelselect directive's scope.
In your channelselect directive's definition, you can do something like the following:
directive('channelselect', [function () {
...
scope: {channel: '='}
...
}])
This will create an isolated scope for your channelselect directive, and will let you use the channel attribute on your <channelselect> tag to set up a bi-directional binding to its parent scope.
So now you can do this in galleryEdit.html:
<channelselect channel="gallery.channel"></channelselect>
Now channelselect's $scope.channel will be bound to galleryEdit's $scope.gallery.channel.
See the Directive Definition Object section of AngularJS's Directives guide for more details on isolated scopes.

Resources