I have a AngularJS SPA application. The main page includes an ng-view directive and a textbox with ng-model bind.
I have some views that display inside ng-view. I have a variable is shared between these views so I used a service for that.
My Issue is when I click a button inside the views this variable changed. I want to display the changed value inside the textbox in main page as soon as it changed.
My Code is As below:
<div data-ng-app="demoApp">
<div ng-controller="testController">
{{countResult}}
</div>
<ng-view class="content"></ng-view>
</div>
I update counterResult inside view which is loaded in ngview. I want the counterResult get updated.
so you want to access a value from outside of the ng-view scope, in the inside of the ng-view scope. check this code, which I've tested on jsbin and it works fine:
index.html:
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular-route.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div data-ng-app="demoApp" ng-init="data.countResult='test'">
<div ng-controller="testController">
Outside ng-view: {{data.countResult}} <br>
</div>
<ng-view class="content"></ng-view>
</div>
</body>
</html>
and your app.js file which you have to add in index.html file:
angular.module('demoApp', ['ngRoute'])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
template: '<div>Inside ng-view: {{data.countResult}}<br><input ng-model="data.countResult"/></div>',
controller: 'viewMainController'
})
.otherwise({
redirectTo: '/'
});
}])
.controller('testController', ['$scope','$rootScope', function($scope, $rootScope){
}])
.controller('viewMainController', function($scope){
});
Here in your testController scope you're defining the countResult value which will not be found in another scope that isn't prototypically inherited from testController. Here you ng-view isn't child of testController so it won't get the value of countResult. So here you can put you countResult value in the $rootScope. As all $scope are children of $rootScope it will get the value in side the ng-view. Hope the explanation make sense.
Related
I have a problem. I create a component in AngularJs and I want to pass data from controller to Component.
Data comes to template component, but in the controller on component is undefined!
This is my code.
The controller
angular.module('testModule')
.controller('testController', ['$scope',
function($scope){
var vm = this;
vm.name = "John";
}
]);
The component. Here in the console.log(vm.name) its undefined! This is my problem.
angular.module('testModule')
.component('testComponent', {
bindings: {
"name": '='
},
controllerAs: 'ctrl',
controller: ['$scope', function ($scope) {
var vm = this;
console.log(vm);
console.log(vm.name);
}],
template: "<h2>Hi {{ctrl.name}}</h2>",
});
HTML
<html ng-app="testModule">
<head>
<title>Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<script src="app.module.js"></script>
<script src="testController.js"></script>
<script src="testComponent.js"></script>
</head>
<body>
<div ng-controller="testController as ctrl">
<test-component name="ctrl.name"></test-component>
</div>
</body>
</html>
Here is the Plunker
Any idea? Thanks!
You should be hooking up over $onInit method to see what component bindings has.
vm.$onInit = function(){
console.log(vm.name);
}
The things which you were trying to do was totally doable till angular 1.5.X, but since AngularJS 1.6+ version they disabled prepopulating context of controller by introducing preAssignBindingsEnabled over $compileProvider. By default it is set to false. If you really want to see this working you could try to set the flag by below code(but I'd not recommend to use this). The main reason behind introducing this change is to make Angular and AngularJS API to look similar by design & architecture, eventually it will make one step closer to migration to Angular.
.config(function($compileProvider){
$compileProvider.preAssignBindingsEnabled(true);
})
Plunker
I've been trying to figure this out for a few hours now, and I can't seem to find the problem. I've read some other questions with similar problems, but they don't have any solutions that have worked for me.
I am having trouble registering my controllers. I am not able to register controllers outside of the file in which I declare the app. Originally, I set up the 'MainController' in a separate file, which failed. I was getting an error saying that "The controller with the name 'MainController' is not registered". Once I put MainController in the same file as the app is declared, there were no problems. However, when I have a lot of code, I don't want all the controllers in the same file, as it will become too difficult to read. Here are examples of my code:
angular.module('myApp', ['ngRoute']);
angular.module('myApp')
.controller('MainController', MainController);
I am keeping other controllers in different files, and they are not registering. For example, in home.controller.js:
angular.module('myApp')
.controller('HomeController', HomeController);
function HomeController(HomeService) {
}
This controller will not register, and I don't know why. Each HTML partial in ng-view has its own controller, and the ng-view is within the MainController. Here is the app.config.js file:
angular.module('myApp')
.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/home', {
templateUrl: 'views/home.html',
controller: 'HomeController as home'
}).when('/profile', {
templateUrl: 'views/profile.html',
controller: 'ProfileController as profile'
});
$locationProvider.html5Mode(true);
});
Here is index.html:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<title>My App</title>
<script src="vendors/angular.min.js"></script>
<script src="vendors/angular-route.min.js"></script>
<script src="scripts/app.module.js"></script>
<script src="scripts/app.config.js"></script>
<scripts src="scripts/home.controller.js"></scripts>
<scripts src="scripts/profile.controller.js"></scripts>
<script src="scripts/main.service.js"></script>
<script src="scripts/home.service.js"></script>
<script src="scripts/profile.service.js"></script>
<base href="/" />
</head>
<body ng-controller="MainController as main">
<header>
<h1>My App</h1>
</header>
<!-- Content varies -->
<div class="container">
<ng-view></ng-view>
</div>
</body>
</html>
I have successfully built projects like this in the past without problem, but I can't find any issue compared to those projects. Any help is appreciated!
When I've had this issue in the past, it was related to script loading order, especially with using async script loading. You don't appear to be doing that.
To troubleshoot:
Fire a console log statement inside the controller's function body (console.log('registering controller x')). This statement will either not show up, or will show up after the error.
Angular used to (and I presume it still does) try to wait for app to load and all controllers to register to app before running the code. Either Angular isn't waiting on this controller, or this controller isn't running.
From there, you would verify that the reference to the file is correct (put a console.log at the top of the file), or determine how Angular decides when it believes all controllers are loaded and why it doesn't wait on your controller.
I haven't dealt with Angular since 1.2, because I think it's a pretty bad framework. But that was my experience then, and it seems like the same basic architecture for this. Back then it was relying on Document.ready. I really hope they don't do that anymore (that's where I ran into my async script loader problems).
Best of luck.
newbie to AngularJS here.
I created one AngularJS application using Yeoman, grunt and bower.
The index page contains some style and ng-app and ng-view.
index.html
<html>
<head>
<!-- CSS Imports -->
</head>
<body ng-app="MyApp1">
<div>
//Some divs here to have some styles
<div ng-view></div>
</div>
</body>
<!--importing AgularJS, app.js, controller JS files -->
</html>
app.js
'use strict';
angular.module('MyApp1', [])
.config(function ($routeProvider,$locationProvider) {
$routeProvider
.when('/', {
redirectTo: '/main'
})
.when('/invoice', {
templateUrl: 'views/invoice.html',
controller: 'UploadController'
})
.when('/main', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/login', {
templateUrl: 'views/login.html',
})
.otherwise({
redirectTo: '/main'
});
// $locationProvider.html5Mode(true);
});
angular.module('LoginApp', [])
.config(function ($routeProvider,$locationProvider) {
});
The index page has ng-view that will display invoice.html or main.html. Default is main.html.
main.html
<div class="hero-unit">
<a ng-href="views/login.html" target="_self">Login</a>
<br>
<a ng-href="#invoice">New Document</a>
</div>
Ok. In this main.html, I have two links. Second is a link to invoice. That anyway will display inside index.html ng-view. The controller UploadController belongs to MyApp1 module. And it has separate JS file. It is working fine.
The first link is to another HTML page. Its login.html. It has another ng-app called LoginApp. Both the modules are independent and in diferent pages.
When I click on the first link, it goes to login.html. But in the URL it shows like http://localhost:9000/views/login.html. But I want it to be shown like http://localhost:9000/login, just like for other main.html (http://localhost:9000/#/main). When I edited the link like <a ng-href="#login">Login</a> it is not working.
And also $locationProvider.html5Mode(true); is not working for me.
Put the login.html to same folder like index.html.
I think it's not possible to route to another module. However this route rule for login.html will not working for (external) page.
I'm trying to build an angularjs application. Everything seems fine, there is no error, but it's not working. To remove other factors, I removed everything (requirejs etc.) and dumbed it down to a small html file.
Here is the js code in html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script>
angular.module('application', ['ngRoute']);
angular.module('application').config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {template: 'test content', controller: 'controller1'});
$routeProvider.otherwise({redirectTo: '/'});
}]);
angular.module('application').controller('controller1', ['$scope', function($scope) {
console.log('in controller1');
}]);
angular.bootstrap(document, ['application']);
</script>
</head>
<body>
</body>
</html>
Result I'm expecting to see is "test content" on page, and 'in controller1' in my console.
Can you tell me why it's not working?
Your are missing the ng-view directive that works together with the routes to display the template provided in the route config.
Working plunker
Code:
<body>
<div ng-view></div>
<script>
angular.module('app', [])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {template: '<p>test content</p>', controller: 'controller1'});
$routeProvider.otherwise({redirectTo: '/'});
}])
.controller('controller1', ['$scope', function($scope) {
console.log('in controller1');
}]);
angular.bootstrap(document, ['app']);
</script>
</body>
Angular JS bootstraps by using ng-app and ng-controller directive declared in html.
Refer this:
http://docs.deployd.com/docs/collections/examples/a-simple-todo-app-with-angular.md
Try adding adding this document ready test around you bootstrap call. It'll wait to call bootstrap until the document (DOM) is completely ready.
If you don't wrap bootstrap in the ready() call the browser may still be in the middle of constructing the DOM when angular builds it's view of the DOM. This can lead to angular being unaware of parts of your page, or worse (and this can be tough to debug).
angular.element(document).ready(function() {
angular.bootstrap(document, ['application']);
};
You can read more about that in this guide to angular initialization: http://docs-angularjs-org-dev.appspot.com/guide/bootstrap
Or you could use <html ng-app='application'> instead as others have mentioned if you want to go the more traditional route- but then you'd have to get rid of the angular.bootstrap call.
I am trying to bind a route property to the src for ng-include:
config.js
$routeProvider.when('/services', {
templatePATH: '/views/services.html'
});
index.html
<html lang="en" ng-app="myApp" ng-controller="AppController">
<body>
<div ng-include src="{{page}}" class="container"></div>
</body>
</html>
controllers.js
controller('AppController', ['$scope','$route','$routeParams', function($scope, $route, $routeParams) {
var render = function(){
$scope.page = $route.current.templatePATH;
};
$scope.$on("$routeChangeSuccess",function( $currentRoute, $previousRoute ){
render();
});
}]).
Here's where I got the idea. What is strange is that the value of templateURL can be seen in the DOM on pageload where src is injected from the ng-include directive. Sadly however, this is not working.
Is it possible to achieve this kind of convention?
Oh your are just making a very small mistake please change your code to below
<div ng-include="page" class="container"></div>
More Detailed Answer :
When you use ng-include directive a watch is put on srcExp which is value of attr.ngInclude || attr.src so if you do {{page}} then you will be watching on the value of page not on page property so you have to put "page" without interpolated value so that it can watch directly on page instead of page string value