Defining function to be run on every page load - javascript

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);
}
} );

Related

Checking if <video> tag can display a media and handling an error in Angular

My goal is to check if HTML5 video element can display a video from given src. I build my application using Angular. Below is how my html component's template and controller look.
Every model passed to component's controller has it own path and name. When path points to valid mp4/webm/ogg file - it is displayed perfectly. But I want to check if a file from given path is supported. in case of error I'd show to user a dialog saying {{vm.name + 'cannot be displayed'}}
There are plenty of methods of HTML Audio/Video DOM Reference from w3 but i simply don't know how to use them. Moreover I noticed that I can't use inline js in template html file of a component.
http://www.w3schools.com/tags/ref_av_dom.asp
So? How to check if a file can be shown in video tag?
video-preview.html
<header class="dialog-header">
<span>{{vm.name}}</span>
<button type="button" class="btn btn-icon close-btn icon-close" ng-click="vm.closeDialog()"></button>
</header>
<div class="dialog-content">
<video class="video-preview-dialog" id="myVideo" autoplay src="{{vm.path}}" controls></video>
</div>
video-preview-dialog.controller.js
(function () {
'use strict';
angular
.module('videoApp')
.controller('VideoPreviewDialogController', VideoPreviewDialogController);
/** #ngInject */
function VideoPreviewDialogController(model, VideoDialogInstance) {
var vm = this;
vm.path = model.path;
vm.name = model.name;
vm.closeDialog = closeDialog;
function closeDialog() {
PreviewDialogInstance.cancel();
}
}
})();
The answer was to pass a function with "&" sign from a controller to directive, and invoke it when error occurs.
1. Link tag in dirctive
2. Set to player eventListener("error", passedFunction())
That was it

ng-repeat when data is ready

I have a website with two webpages:
A settings page: webpage with JSON content that looks like this:
{"Sources":["1","2","3","4"]}
A webpage that present all the known "sources" in the system. Just print them one after another.
When my application loading, I downloading the sources page, and save in on my scope at $scope.Settings.Sources.
My AngularJS code:
$scope.getSettings = function (ID, successCallback, failureCallback)
{
$scope.ID = ID;
$http.get("/sources?ID=" + ID).then(function (response)
{
if (response.status == 200)
{
$scope.Settings = response.data;
successCallback();
}
else
{
failureCallback();
}
});
}
function getSettings_success()
{
// Ready to update the ng-repeat NOW.
}
function getSettings_error()
{
alert('Error');
}
$scope.getSettings(1, getSettings_success, getSettings_error);
Now, when i have the $scope.Settings.Sources ready, all I have to do is to print each soruce in specific HTML template. Because of that, I was thinking to use the ng-repeat for this task. Something like this:
<div ng-init="sources=$scope.Settings.Sources">
<ul>
<li ng-repeat="source in sources">
{{ source }}
</li>
</ul>
</div>
Unfortunately, this code isn't working. This because when the page is loading, the $scope.Settings.Sources isn't ready yet. So, the ng-repeat must run after the "sources" page was downloaded.
Is this possible? If yes, how?
You shouldn't be using ng-init for such case, because data is coming by Ajax and you are assigning blank object to source. Cause doesn't responded yet. Rather I'd use Settings.Sources variable directly on your view.
Markup
<div>
<ul>
<li ng-repeat="source in Settings.Sources">
{{ source }}
</li>
</ul>
</div>
Side Note: $scope variable's directly accessible inside angular directives, you don't need explictly specify $scope

Change AngularJS url/route from html - javascript code

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.

Same controller for multiple ng-app

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);

Embedding AngularJS in existing jquery/bootstrap based website

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;
};
}
};
}
]);

Categories

Resources