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.
Related
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;
I want to use Angular-route to change the controller used in a page
This is some part of my angular code
var cat_list = angular.module('getCat', ['ngRoute']);
cat_list.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('category/upcoming', {
controller: 'getUpcoming'
})
.when('category/popular', {
controller: 'getPopular'
});
$locationProvider.html5Mode(true);
});
cat_list.controller('getUpcoming', ['$scope', function($scope, $routeParams) {
//controller code goes here
});
cat_list.controller('getPopular', ['$scope', function($scope, $routeParams) {
//controller code goes here
});
and this is some part of my html
<div class="row" ng-app="getCat">
<div class="col-md-12">
<!-- something happen in here -->
</div>
</div>
but when I tried to visit http://localhost/project/category/upcoming or http://localhost/project/category/popularthe route is not working (no controller picked or selected)
did I miss something?
Try this
var cat_list = angular.module('getCat', ['ngRoute']);
cat_list.config(['$routeProvider', '$locationProvider',
etc etc.
Could you also please explain why you want to use different controllers on the same page? Why dont you use two different partials to create two seperate pages for upcoming and popular?
Or, a different approach would be to just use the same controller, and filter your results using the appropriate directive, without changing the stuff that you load each time.
Have to mention ng-view, so that this directive is the placeholder to replace your view partials on url changes.
<div class="row" ng-app="getCat">
<div class="col-md-12">
<div ng-view></div> // ---- This is the thing you missed
</div>
</div>
I am beginner in angular js
HTML
<div ng-app="myapp">
<div ng-controller="maincontrol">
<div ng-show="!vis">show</div>
<div ng-show="vis">hide</div>
</div>
<div ng-view></div>
</div>
JS
var app = angular.module('myapp', ['ngRoute'])
app.controller('maincontrol', function ($scope) {
$scope.vis = true;
$scope.fun = function () {
if ($scope.user == "home" && $scope.pass == "home") {
console.log($scope.user, $scope.pass);
$scope.vis = false;
}
}
})
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'home.html'
})
.when('/contact', {
templateUrl: 'contact.html'
})
});
and also i have two html pages like
home.html
<div ng-controller="maincontrol">
<input ng-model="user"/>
<input ng-model="pass"/>
<div ng-click="fun()">
click
</div>
</div>
contact.html
<div>
contact
</div>
my expectation is after entering home into user and pass. if i click 'click' i need to show 'show' label instead of 'hide'. pls help me.
Each controller has its own scope, when you wrote $scope.vis=false on fun(), you actually created a new variable on maincontroler1 scope. If you expected this variable to affect the view which is binded to maincontroler scope, it won't happen.
I suggest 2 options:
You can use one controller for entire app (If you use same controller in two tags it will still create a new scope although it is the same controller), this way the fun() method that was called from the first view will change the boolean in the single controller and will affect the second view. Please note when you use ng-view you will have to get the variable from the parent.
So I used this code:
$parent.user
$parent.pass
Create this working plunker for you.
Share the vis boolean between 2 controllers using a service. You can
use this post for this option.
You can also use reach parent controller scope from child controller, that can be done if ng-view will be nested in the outer controller. You can use this post for option 3.
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 have two separate views (named view1.html and view.html) with separate controllers (named controller1 and controller2) and they are routed using config:
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/view1', {templateUrl: 'view1.html', controller: controller1}).
when('/view2', {templateUrl: 'view2.html', controller: controller2}).
otherwise({redirectTo: '/view1'});
}]);
view1 and view2 have a shared part of template code, so I extracted it into a new template view (named view3.html) and use ng-include in view1.html and view2.html:
<span ng-view="">
...
<span ng-include="'view3.html'"></span>
....
</span>
also view3.html logic is independent from the controller1 and controller2, so the scope variables needed in veiw3.html is repeated in both of the controllers:
function controller1($scope){
...
some code to calculate $scope variables for view3
...
}
function controller2($scope){
...
same code to calculate $scope variables for view3
...
}
My question: is there any way to extract repeated codes in controllers into a separate controller for view3? I add ng-controller for view3 but it doesn't work:
<span ng-controller="controller3">
view3.html template codes here
</span>
I guess it's because view3.html is included in an element with ng-view directive and can not have a separate controller.
I think you can use ng-include to achieve it:
In view1.html
<div ng-include src="'view3.html'"></div>
//other template for view1
In view2.html
<div ng-include src="'view3.html'"></div>
//other template for view2
In view3.html
<div ng-controller='controller3'>
//template for view3
</div>