In Angularjs using ng-include im facing some trouble...
Im having a single html form and including other html within it.
If this is my main.html..
<div ng-controller="appCtrl">
<div ng-include src="'/Tab1.html'"></div>
{{data.name}}
<!--trying to use one of the Tab1 field but unable to fetch -->
<button type="submit" ng-click=save()>Save</button>
</div>
in Tab1.html
<div ng-controller="appCtrl">
<input type="text" ng-model="data.name">
{{data.name}}<!--getting the value here-->
</div>
in my controller
angular.module('app')
.controller('appCtrl', ['$scope', '$http','$routeParams','$rootScope' ,'$location',
function($scope, $http, $routeParams, $rootScope ,$location){
$scope.save= function(){
console.log($scope.data);//undefined...
}
})
Must be minior mistake but not known where...Thanks in advance for fixing!!
ng-include creates a child scope to acces the parent scope use $prarent
in Tab1.html
<div>
<input type="text" ng-model="$parent.data.name">
{{$parent.data.name}}<!--getting the value here-->
</div>
Do like this
<div>
<input type="text" ng-model="data.name">
{{data.name}}<!--getting the value here-->
</div>
Remove controller in child div and it will take current scope;
also in controller use
$scope.data={name:""};
$scope.save= function(){
console.log($scope.data);
}
and it will work;
Related
I am learning how to use ngRoute to split my html forms into separate views. When I add data to the main array in the index.html the array updates correctly, but when I try the same approach in the html forms that are added in through the ng-view, the array does not render correctly. I can debug and see that the array is getting the new name added, but it will not render on the html.
Index.html
<h1> Names </h1>
<ul ng-repeat="name in names">
<li>{{name.fname}}</li>
</ul>
<h1>Add name in index.html</h1>
<input type="text" ng-model="name" />
<button ng-click="addName(name)">add name</button>
<ul>
<li> First</li>
<li> Second</li>
</ul>
<div class="container">
<div ng-view></div>
</div>
Apps.js
var myApp = angular.module('myApp', ['ngRoute']);
myApp.config(function ($routeProvider) {
$routeProvider
.when('/first', {
templateUrl: 'pages/first.html',
controller: 'mainController'
})
.when('/second', {
templateUrl: 'pages/second.html',
controller: 'mainController'
})
});
myApp.controller('mainController', ['$scope', '$log', function($scope, $log) {
$scope.names = [{fname:'john',lname:'doe'},{fname:'jane',lname:'doe'}];
$scope.addName = function(name){
$scope.names.push({fname:name,lname:'no last name'});
}
}]);
first and second.html are identical
<h1>Add name in first.html</h1>
<input type="text" ng-model="name" />
<button ng-click="addName(name)">add name</button>
This is by design.
The $scope is limited to the scope of the controller, which is everything that is rendered inside the ng-view. This means there are two collections named names, one on the app scope, and one on the controller scope. When you modify the names collection inside the controller, it only modifies this collection, not the one referenced in the root level of the app. (I am assuming that you bind mainController to the body tag, otherwise the addName() in index.html wouldn't work. This by itself is not a great choice, you should not put another controller instance into itself, unless you absolutely know what you are doing.)
The proper way to handle this situation is to put the names collection and the addName() function into a service that you inject into your controllers.
I have an ng-repeat that loads an ng-include. I'd like to have a separate controller inside the view that the ng-include loads.
But I'm having trouble accessing the item from ng-repeat in that controller. I tried something like this, and it fails.
How do I get at result inside of SubController?
<div ng-repeat="result in results">
<div class="box" ng-include="view/someinclude.html"></div>
</div>
view/someinclude.html:
<div ng-controller="SubController">
...
</div>
controller js:
angular.module('SubController', [])
.controller('SubController', ['$scope',
function ($scope) {
//fails
console.log($scope.result);
}
]);
Make sure your scopes are a part of the same module, or they they're different include one in the other, if that's not the problem then it'll be something outside what you've shown, as something like this:
angular.module("app").controller.(testController", ["$scope", function($scope){
console.log($scope.x)
}])
with:
<div ng-repeat = "x in [1,2]">
<div ng-include = "'./views/vew.test.html'">
</div>
</div>
and in vew.test.html:
<div ng-controller = "testController">
{{x}}
</div>
Will wack 1 and 2 on the screen and in the console.
Make sure you're using the same module:
angular.module('SubController').controller('SubController', function() {...});
Try using $parent.result instead of $scope.result inside your controller as ng-include creates a new scope of its own that prototypically inherits from its parent scope.
I was looking this example AngularJS ng-model $scope in ng-repeat is undefined in this question first answered by #Gloopy here http://jsfiddle.net/VnQqH/128/
My question is can I update ng-model values in ng-repeat scope from outside of ng-repeat scope like this:
<div ng-app="MyApp">
<div ng-controller="PostCtrl">
<div ng-repeat="post in posts">
<strong>{{post}}</strong>
<input type="text" ng-model="postText">
</div>
/*Update ng-model values (in ng-repeat scope) using single click*/
save post
</div>
</div>
Here is controller:
angular.module('MyApp',[]);
function PostCtrl($scope) {
$scope.posts = ['tech', 'news', 'sports', 'health'];
$scope.savePost = function(post){
alert( 'post stuff in textbox: ' + post);
}
}
I tried but got undefined :( My experimental fiddle is here http://jsfiddle.net/hot81o2z/ If anyone has the solution for this problem please share. Many thanks in advance.
You can make use of $parent in order to pass a scope variable outside of the ng-repeat directive, something like this
HTML:
<div ng-app="MyApp">
<div ng-controller="PostCtrl">
<div ng-repeat="post in posts">
<strong>{{post}}</strong>
<input type="text" ng-model="$parent.postText">
</div>
<!--Update on single click-->
save post
</div>
</div>
Controller: Not changed anything, kept what you had
Working Demo
I'm trying to do the following:
Type something in a search box, perform the related search and show the result defined in a separate view template.
The search thingy is part of a page header and so, my index page is as follows:
index.html
<div class="row search-box">
<div class="col-md-2"></div>
<div class="col-md-6">
<form id="myForm" class="form-inline form-search"
style="padding-left: 10px">
<!-- Search box -->
<input id="in" type="text" ng-model="searchTerm" placeholder="Search for products, categories or brands"
class="search-query input-search">
<button class="btn searchBtn" ng-click="doSearch()" ng-controller="MediaListController">
<i class="icon-search"></i>Search
</button>
</form>
</div>
<div class="col-md-3">
<div class="btn btn-blue cart-btn-cont">
<span class="cart-icon"></span>
</div>
</div>
</div>
...
<div ng-view></div>
Controller (relevant function)
$scope.doSearch = function () {
var type = $scope.mediaType;
$scope.foundItems = MediaService.search().length;
console.log("Found items :"+ $scope.foundItems + "for search term :"+ $scope.searchTerm);
$location.path("/search");
}
app.js
var app= angular.module('sampleApp', ['ngRoute','ngResource','mgcrea.ngStrap']);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/login', {templateUrl: 'app/views/partials/login.html', controller: 'LoginController'});
$routeProvider.when('/search', {templateUrl : 'app/views/partials/tpl/search_result.tpl.html'});
$routeProvider.when('/', {templateUrl: 'app/views/landing_page.html', controller: 'MediaListController'});
$routeProvider.otherwise({redirectTo: '/'});
}]);
Search result template:
Found {{ foundItems }} product(s) for search phrase <i>"{{searchTerm}}"</i>
It all works fine, but in getting to this stage, I am confused by the following:
a. Why is $scope.foundItems not visible in the template i.e, {{foundItems}} works only when I use $scope.$parent.foundItems in the controller?
b. If a new child scope is being created, how come $scope.searchTerm is available in the view template i.e., {{searchTerm}}? Is it because ng-model="searchTerm" creates a model binding in the rootScope?
c. I also saw that {{foundItems}} in the template worked fine if I used $rootScope.foundItems, but what if I want to avoid $rootScope - is the use of $scope.$parent valid?
Thanks in advance.
a. Why is $scope.foundItems not visible in the template i.e, {{foundItems}} works only when I use $scope.$parent.foundItems in the controller?
I think it's a little strange to assign the same controller in the ng-view and then another tag like button. Because button will create its own scope right there. And then ng-view also creates one.
b. If a new child scope is being created, how come $scope.searchTerm is available in the view template i.e., {{searchTerm}}? Is it because ng-model="searchTerm" creates a model binding in the rootScope?
that scope has nothing to do with the doSearch scope actually.
c. I also saw that {{foundItems}} in the template worked fine if I used $rootScope.foundItems, but what if I want to avoid $rootScope - is the use of $scope.$parent valid?
You should probably have a main controller for the page and then call everything from there perhaps.
I'm creating a form in HTML using ng-repeat to generate the form elements from an object in the scope. I also use that object to generate other elements outside of the ng-repeat.
A simplified example looks like this in HTML:
<div ng-app="App">
<div ng-controller="Ctrl">
<div class="block1">
<form ng-repeat="(key, value) in test">
<label>{{key}}</label>
<input ng-model="value" />
<p>{{value}}</p>
</form>
</div>
<div class="block2">
<p>
{{test.a}}
</p>
<p>
{{test.b}}
</p>
</div>
</div>
</div>
and this in JS:
angular.module('App', []);
function Ctrl($scope) {
$scope.test = {
a:"abc",
b:"def"
}
}
In this example, the text in block2 is set to the initial values of test.a and test.b. The input values and <p> values inside of the loop are also set to the initial value.
When I modify the values within the inputs, the <p> values inside of the ng-repeat block update correctly, but the <p> tags in block2 fail to update.
Why is this the behavior? Does ng-repeat create its own isolated scope? If so how can I get the controller level scope to update? Also, could somebody explain the thinking behind this behavior and any advantages it provides?
JSFiddle Showing the problem
ng-repeat creates a child scope for each repeated item. As a result you are trying to pass a primitive to child scope which won't create a reference to parent. When you pass objects however, you pass the original object reference.
From the mouth of one of the fathers of Angular:
Always have a dot in ng-model
This is a great video regarding Angular Best Practices given by Angular creator (2012/12/11). Go to minute 31 for well explained detail of this exact situation
Modify data to array of objects:
$scope.test = [{ val:"abc",key:'a'}, {val:"def",key:'b'} ]
Then in repeater:
<form ng-repeat="item in test">
<label>{{item.key}}</label>
<input ng-model="item.val" />
<p>{{item.val}}</p>
</form>
DEMO
try this:
angular.module('App', []);
function Ctrl($scope) {
$scope.test = [
{label:"a", value:"abc"},
{label:"b", value:"def"}
]
}
and
<div ng-app="App">
<div ng-controller="Ctrl">
<div class="block1">
<form ng-repeat="o in test">
<label>{{o.label}}</label>
<input ng-model="o.value" />
<p>{{o.value}}</p>
</form>
</div>
<div class="block2">
<p>
{{test[0].value}}
</p>
<p>
{{test[1].value}}
</p>
</div>
</div>
</div>
Angularjs uses the fact that objects are passed by reference. So, if you pass a object to a function and change the object inside the function, the object outside also changes.
Look at this updated JSFiddle