I have a single webpage, that have different documents.php, each document with its ng-app and some controllers. (My webpage is similat to spotify).
player.php: (Where the user can play some music with an audio player)
<div class="navbar-fixed" ng-controller="menuController as menu2">
<?php include('includes/menu.php'); ?>
</div>
<div ng-controller="InteractiveController as interactCtrl">
//some code
</div>
panel_admin.php: (where the user can modify its data and some data of the webpage)
<div class="navbar-fixed" ng-controller="menuController as menu2">
<?php include('includes/menu.php'); ?>
</div>
<div ng-controller="AdminController as AdminCtrl">
//some code
</div>
player.php and panel_admin.php have its respective player.js and panel_admin.js with its .controllers.
player.js:
var decibelsInteractive = angular.module("decibels-interactive", []);
decibelsInteractive.controller('InteractiveController', function ($scope, $log) {
panel_admin.js:
var adminControl = angular.module("decibels-admin", []);
adminControl.controller("AdminController", function($scope){
Now, I have the menu bar in menu.php, where I use in player.php, and in panel_admin.php document. I import it because I don't want to repeat code in every page where I need to use the menu (menu.php have options like manage user options, logout, and many others...). I also have created a menu.js to only have the specific methods in one document and not in 25 documents.
menu.php: (menu is a menu bar where the user have some options, and it also have its username and logout option)
//this document only contains some html code
Now, I've tried to implement a simple code (in menu.js) that allows me to share one controller when I have many ng-app.
Question with the code I've taken
menu.js:
angular.module('decibels-interactive', ['shared']); //player2.php
angular.module('decibels-admin', ['shared']); //panel_admin.php
var sharedModule=angular.module('shared',[]);
sharedModule.controller('menuController',['$scope',function($scope) {
alert("menuController");
}]);
});
And this worked!!! But then, angular shows an error... (loading player.php)
Error: [ng:areq] http://errors.angularjs.org/1.2.25/ng/areq?p0=InteractiveController&p1=not%20a%20function%2C%20got%20undefined
And when I load panel_admin the same error appears again, but with the AdminController...
It seems like that angular only detects the first controller in each .php, and can't find the second one.
What am I doing wrong?
Thank you!
You can create a file for your shared code and have the controller code inside it.
// #file mySharedCode.js
var MySharedCode = MySharedCode || {};
MySharedCode.menuController = function($scope) {
// controller logic
};
Then, in your app.js file call menuController function
// #file app.js
sharedModule.controller('menuController', MySharedCode.menuController);
Related
Say I have a button that's within the ng-app scope, but outside the ng-controller/ng-view scope.
<html ng-app="myApp">
<!-- ... -->
<body>
<button id="myButton">Click me!</button>
<div ng-view> <!-- angular-view --> </div>
</body>
</html>
And I want to change the URL/Route when I click the button.
var button = document.getElementById('myButton');
button.addEventListener('click', function() {
//code that changes path.
});
How do I do that? If I try window.location.href = '/'; the whole page gets reloaded, not just the view. $location isn't visible from html javascript, so that's not an option neitehr.
If anyone knows a way I can change the path/route/url from javascript, I'd be more than happy to accept any valid answer, or a redirect to some helpful documentary post, or a rederect to another SO question, because I'm trying to find an answer to this for a while and I've got nothing...
I'll note that I tried making a global scope function, but that didn't work, neither.
angular.module('myApp', [])
.config( ... )
.run(function($rootScope, $location) {
$rootScope.setUrl = function(url) {
$location.path(url);
};
})
.controller(
.....
and called with setUrl('/');, $root.setUrl('/'); and $rootScope.setUrl('/');, but still nothing ('undefined').
note: the button script is just an example, the real purpose why I'm asking this is a little bit larger, so I'm trying to simplify.
If your purpose is to change route from outside of the Angular app, then you need to change location hash part:
window.location.hash = 'new-route';
Inside Angular controller use $location.path method.
We are working with jquery 1.9.1 and angular 1.2.13. We are using a wysiwyg editor that works great, we save the html into the database and load the html back using jquery append function and works fine. Now we are trying to append the same html into a div tag (the wysiwyg editor also uses a div) and the append function it's not working. We check in the console, and the string we are trying to append is there, also jquery grabs the element (also checked in the console log) but the append function it's not working.
PD: I apologize for my english
The html
<div data-ng-controller="PreviewCtrl">
<div class="container">
<div id="resumenPreview"></div>
</div>
</div>
The controller
angular.module('module').controller('PreviewCtrl', ['$scope', '$routeParams', '$location', '$http', 'selectedElement',
function ($scope, $routeParams, $location, $http, selectedElement) {
$scope.id = $routeParams.id;
$scope.mensaje = $scope.id;
$scope.imagen = null;
$scope.dataImagen = null;
//is not working either
$('#resumenPreview').append("hola");
$scope.pageLoad = function () {
var x = selectedElement.data.Resumen;
//This is properly displayed in the console
console.log(x);
//This too, is displayed in the console log
console.log($('#resumenPreview'));
// Why this isn't working? I'am clueless
$('#resumenPreview').append(x);
};
$scope.pageLoad();
}]);
My guess would be there are multiple divs with id="resumenPreview". But this is clearly the wrong way to handle such things in angular. There shouldn't be dom-manipulation in the controller - directives should take care of dom-related stuff. Put the html-string into the scope and let angular handle the injection into the dom:
instead of $('#resumenPreview').append(x); do $scope.resumenPreview = x;
and in the template do this:
<div class="container">
<div ng-bind-html="resumenPreview"></div>
</div>
Solve it with angularjs for the ng-bind-html to work it's necessary to include
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular-sanitize.js"></script>
and to add 'ngSanitize' as a dependency in the app module configuration. And then just do what #Johannes Reuter posted.
Thanks everybody, Greetings.
I am designing a site which has a fixed data set (17 records - each representing a 'book' for sale) and allows navigation between several pages that display details about each of the books. The problem I am having is that when the hyperlink goes to a different view, everything works fine, but if it is hyperlink is to a different book of the same view, it fails to run the controller script. How do I force this to be done.
I have made a minimal executable example:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.min.js"></script>
<script>
var fooApp = angular.module('fooApp', []);
fooApp.controller('fooCtrl', function ($scope) {
$scope.books = ["Book1", "Book2", "Book3", "Book4", "Book5"]
$scope.selectedBook = "Book1";
var curPath = window.location.toString();
var hashPos = curPath.indexOf("#/");
if (hashPos>0) {
$scope.selectedBook = curPath.substring(hashPos+2);
}
});
</script>
</head>
<body ng-app="fooApp" ng-controller="fooCtrl">
Selected Book: {{selectedBook}}
<ul>
<li ng-repeat="book in books">Visit A {{book}}
</li>
</ul>
<ul>
<li ng-repeat="book in books">Visit B {{book}}
</li>
</ul>
</body></html>
Save the above to two different files: PageA.htm and also as PageB.htm. The selected book is passed as a parameter after the hash mark. You will see the behavior as this: When on PageA you can click on a link to PageB and the book is selected appropriately. But if you click on a link to PageA the URL changes in the address bar, but the controller function does not apparently run. Similarly, on PageB, links to PageA will select a book, but links that stay on PageB do not.
I like the fact that the page is NOT re-read from the server ... it comes out of cache, but I would like to somehow trigger the the controller function again so that the new passed parameter can be read and the correct data displayed. What am I doing wrong?
Update One
Some have suggested to add target="_self" to the hyperlink tag. This works in the simplified minimal example above. Unfortunately, it does not work on fully elaborated site. I don't know why. You can check the full site and the problem is that the "Featured-Book" does not display if you are showing the details of any other book.
Ok. It seems you need to use the $location service and $locationChangeSuccess event in order to keep track url changes. These are part of the Angular core API.
fooApp.controller('fooCtrl', function ($scope, $rootScope, $location) {
$scope.books = ["Book1", "Book2", "Book3", "Book4", "Book5"]
$scope.selectedBook = "Book1";
$rootScope.$on('$locationChangeSuccess', function (event, location) {
$scope.selectedBook = $location.path().substring(1);
});
});
It seems that you are trying to implement a route system.
Have you looked into Angular's ngRoute? check out this example.
ngRoute is great because you can access route data via its $route service or simply via $routeParams.
We've got an existing application where the client-side is jQuery / Bootstrap. It consists of many tabs where each tab is defined in a module imported via. require.js. The tab javascript is handed a parent DOM element and is in charge of drawing itself inside of that element.
We'd like to start building new functionality (tabs) in AngularJS and running into some problems doing that.
My thinking is that we could tag the body with ng-app and in the main page code conjur up an app module window.app = angular.module('ourApp', []); and later, as tabs are loaded, create and wire-up the controllers.
I've built a simple single-page example that exhibits the problem we are having (below or here http://jsfiddle.net/p4v3G/1/).
The only way I've been able to get the example to work is manually calling angular.bootstrap which I'm pretty sure is wrong. Also, that only works the first time so if I click the button twice (equivalent to navigating to the tab, away from it, and back again within our app), Angular isn't wired up properly.
I'd appreciate any help.
<body ng-app='testApp'>
<div id="main" style="border: 1px solid #000; background: #ffdddd;">Click button to replace template and wire up controller...</div>
<button id="button1">Load</button>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.14/angular.min.js"></script>
<script>
var app = angular.module('testApp', []);
jQuery(function() {
$("button").click(function() {
// controllers are wired up in click handler to simulate environment where we
// are looking to embed angular inside of an existing bootstrap/jquery application
// where new tabs (loaded as separate modules through require) are loaded on-demand.
app.controller('TestController', function($scope) {
$scope.message = 'Hello World, from Controller #1';
});
$("#main").html('<div ng-controller="TestController">{{message}}</div>');
// Bootstrap works the first click but not subsequent clicks
angular.bootstrap(document, ['testApp']);
});
});
</script>
</body>
To chunk up your appliation so that only the relevant parts are instantiated etc. what you need is angular ui-router. You would then set up a parent state for your tab-control with child states for each of your tabs. That way you both get deep linking and the performance you want with loading only the relevant tab.
As for requirejs, I encourage you to firstly consider if you really need it. In my opinion the javascript making up an angular application is usually much terser than a jquery application due to the declarative nature of the technology. Therefore loading all of the javascript at boot-time is ok. Your templates however may not be as simple, but by using templateUri references to templates they may be loaded as needed. (Personally I prefer compiling them to javascript and placing them in the $templateCahce at the cost of boot-time, but that's another matter.)
That being said, if my observations do not hold for your scenario/application/codebase, then others have had great success incorporating requirejs with angularjs. For a nice introductory talk on that subject see this nice ng-conf video.
Best of luck!
Could you be more precise, what type of errors appears.
You don't need use jquery. Check this code and compare
http://jsfiddle.net/pokaxperia/3w6pb/1/
HTML
<body ng-app='testApp'>
<div ng-controller="TestController">
<span id="main" style="border: 1px solid #000; background: #ffdddd;">{{message}}</span>
<button ng-click="loadMessage();" id="button1">Load</button>
</div>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
</body>
script
var app = angular.module('testApp', []);
app.controller('TestController', ['$scope',function($scope) {
$scope.message = "Click button to replace template and wire up controller...";
$scope.loadMessage = function(){
$scope.message = 'Hello World, from Controller #1';
};
}]);
Or check your code on jsfiddle, but with few variants
http://plnkr.co/edit/fUQDpO?p=preview
HTML
<body>
<example-tabs></example-tabs>
<div class="panel" ng-show="isSelected(1)">Panel One</div>
<div class="panel" ng-show="isSelected(2)">Panel Two</div>
<div class="panel" ng-show="isSelected(3)">Panel Three</div>
</body>
Main script:
var app = angular.module('tabsExample', ['tabDirectives']);
Directive to load Tabs
var app = angular.module('tabDirectives', []);
app.directive('exampleTabs', [
function() {
return {
restrict: 'E',
templateUrl: 'example-tabs.html',
controller: function($scope) {
$scope.tab = 1;
$scope.selectedTab = function(setTab) {
$scope.tab = setTab;
};
$scope.isSelected = function(checkTab) {
return $scope.tab === checkTab;
};
}
};
}
]);
I'm building a songbook (with chords) with PhoneGap. Each song is stored in separate file, index is held in one of the files.
What I need is to be able to run some Javascript function every time a page is pushed. Meaning:
In index.html I have:
<li class="…" ng-click="ons.navigator.pushPage('page.html')">
<span class="topcoat-list__item__line-height">Some song</span>
</li>
What should I put where to run Javascript function when page.html is pushed?
AngularJS Controller resolve this. For example,
<div ng-controller="MyCtrl">
<div ng-click="pushPage('page2.html')"><span>Some song</span></div>
</div>
and in app.js
app = angular.module('myApp', ['onsen.directives']);
app.controller('MyCtrl',function($scope,$rootScope) {
$scope.pushPage = function(pagename) {
/* call some function */
alert("OK");
/* call some function end */
$rootScope.ons.navigator.pushPage(pagename);
}
} );