How can I delay the loading of my controller till the HTML page has been loaded in AngularJS?
I am using the angular spinner. My code is as below
<span spinner-key="spinner-mySpinner">
<div>...</div>
</span>
I am calling the spinner before calling a promise for loading data.
...
mySpinner.spin('spinner-mySpinner');
loadDataPromise = file.getFileDetails(vm.id, vm.path);
...
loadDataPromise.finally(function () {
mySpinner.stop('spinner-mySpinner');
}
...
I am not able to see the spinner.
I think that my controller is getting initialized before the HTML page gets loaded.
Is there a way in which I can delay my controller till the HTML page has loaded?
You can include your controller functionallity inside a function declared inside of your controller as $scope.func = ... And include a js script in your view that on window.load calls that function of your controller.
angular.module('MyModule', [])
.controller('MyController', function ($scope) {
$scope.myfunction = function () {
//do your stuff
};
});
window.onload = function () {
angular.element(document.getElementById('YourElementId')).scope().myfunction();
}
If your are assigning a controller from the route provider you should set an id to your division where you have the ng-view for example id="ngview" and call your function the following way:
window.onload = function () {
angular.element(document.getElementById('ngview')).scope().myfunction();
}
Hope it helps!
Related
I'm very new to angularjs, so this may be a very obvious to a lot of you...
I have a "main" view with a "MainCtrl" controller. The controller has a "$scope.init()" function that is being called when the controller is initialised.
However, I have an iFrame in the view that needs to complete it's "onload" js function before the "init" function can successfully run.
I tried triggering the "init" function using the iFrame's ngInit, but that happens before the "onload"
Please can you tell me how to make init function run after the iFrame's onload="otherFunction" has finished?
Created a demo below where ng-init="increaseCount()" increases the value of $scope.carCount variable but only after the <iframe> was loaded.
You can load the <iframe> by clicking on the button and watch how $scope.carCount changes.
Not sure if this is the right way though.
Basically, I have 2 functions inside my INIT function named increaseCount():
A function increaseCount which contains the main INIT logic ie. increasing the amount of cars
A function onIframeLoad which waits until the iframe is loaded and then executes main INIT logic by calling increaseCount();
Interactive DEMO here or run the code below ↓↓↓
var app = angular.module('App', []);
// Allow iframe loading from various sources
app.config(["$sceDelegateProvider", function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
// Allow same origin resource loads
"self",
// Allow YouTube iframes
"https://www.youtube.com/embed/**"
]);
}]);
// Allow a directive "iframe-onload" in HTML
app.directive('iframeOnload', [function(){
return {
scope: {
callBack: '&iframeOnload'
},
link: function(scope, element, attrs){
element.on('load', function(){
return scope.callBack();
})
}
}}]);
// Main controller
app.controller('MainCtrl', function($scope, $sce) {
$scope.car = 'Mercedes';
$scope.carCount = 0;
$scope.iframeSource = "";
// INIT
$scope.increaseCount = function () {
// First wait on iframe load
$scope.onIframeLoad = function () {
console.log('Iframe fully loaded');
increaseCount(); // If iframe loaded then execute main INIT logic
};
// INIT body - main INIT logic
function increaseCount () {
$scope.$apply('carCount = 10'); // change $scope.carCount to 10
}
};
// Load iframe when clicked on the button
$scope.loadIframe = function () {
console.log("Clicked on the button.");
$scope.iframeSource = "https://www.youtube.com/embed/Ra__OWuOU1M";
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="App" ng-controller="MainCtrl" ng-init="increaseCount()">
<h1>{{ car }} count: {{ carCount }}</h1>
<iframe iframe-onload="onIframeLoad()" ng-src="{{ iframeSource }}"></iframe>
<button ng-click="loadIframe()">Load Iframe</button>
</div>
I'm trying to inject data from a controller to the DOM. What is happening is that the only way i can pass data is whit a ng-click that will trigger an event to getBooks() function that is attached to the view by $scope.
But i want to see my info when i load the page and not by an event like click, i think i need some constructor or similar.
Controller
angular.module('helloWorldApp').controller('homeCtrl',['$scope','$http','$location','$log',
function($scope,$http){
$scope.getBooks = function(){
$http.get('http://localhost:3010/api/books').then(function(resp){
$scope.books = resp;
});
}
}
])
View
<div class="home-page">
{{books}}
</div>
Thanks for the Help
angular.module('helloWorldApp').controller('homeCtrl',['$scope','$http','$location','$log',
function($scope,$http){
function init() {
$http.get('http://localhost:3010/api/books').then(function(resp){
$scope.books = resp;
});
}
init();
])
Use a function and call that function in controller
I have a function defined in a controller , I want to call it in another controller.
I tried to attach it to the $rootscope so I can see in the other controller , but I couldn't .
Is there a way for calling it, without attaching it to the $rootscope?
As far as I know in AngularJS you can share info between controllers in 3 ways:
1 - Creating a Service.
2 - Creating a function linked to $rootScope.
3 - Using events ($broadcast and $on). I use a lot this method in my projects.
I think your problem is that you don't instantiate the controllers in
the proper order or one of them is never instantiated, therefore the
function you want to link to $rootScope in that controller or the broadcast event never fires.
E.G If you want to call a function linked to $rootScope in the 2 controller from the
first one, it is impossible because the 2 controller is instantiated after the first one.
This case happens when you make calls on application runtime.
I will implement your method with some changes:
HTML:
<div ng-controller="MyCtrl_1"></div>
<div ng-controller="MyCtrl_2">
<button ng-click="send()">Send Mess</button>
</div>
JS:
var myApp = angular.module('myApp',[]);
function MyCtrl_1($scope, $rootScope) {
$scope.$on('RenderPage', function (event, PageId) {
$scope.RenderPage = PageId;
alert($scope.RenderPage);
});
};
function MyCtrl_2($scope, $rootScope) {
$scope.MasterPageId = 10;
$scope.send = function(){
$rootScope.$broadcast('RenderPage', $scope.MasterPageId);
}
};
Use carefully $broadcast and $emit, because has different behavior each one.
Try here: http://jsfiddle.net/1ypkb4s9/
Otherwise, post your error.
Simply wrap them with a "father controller":
HTML:
<div ng-app="myApp" ng-controller="myOuterCtrl">
<div ng-controller="myInnerCtrl1">
<button ng-click="outerClick()">Outer Click</button>
</div>
<div ng-controller="myInnerCtrl2">
<button ng-click="innerTwoClick()">Inner Click</button>
</div>
</div>
JS:
angular.module('myApp', []).
controller('myOuterCtrl', function ($scope) {
$scope.outerClick = function () {
console.log('outer click');
}
}).
controller('myInnerCtrl1', function ($scope) {
// nothing here!!
}).
controller('myInnerCtrl2', function ($scope) {
$scope.innerTwoClick = function () {
console.log('inner two click');
}
});
JSFIDDLE.
if you want to use the same function in two or more controllers you might need a service.
or use events
function firstCtrl($scope)
{
$scope.$broadcast('someEvent', [1,2,3]);
}
function secondCtrl($scope)
{
$scope.$on('someEvent', function(event, mass) { console.log(mass); });
}
I have seen a few exmaples on stack overflow about this ng-init issue, although I cant seem to find one which references it with the use of a controller.
I have called the function in the controller by having the following in the html file
<div class="tab-container" ng-controller = "ExampleController" ng-init = "init()" >
In the controller:
$scope.init = function(){
alert("do something");
};
It does run, but it runs before the components have loaded on the screen.
Am i missing something?
Thanks
ng-init is supposed to work like this, because it's used to initialize data.
A very simple example:
<ul ng-init="list = [1,2,3,4]">
<li ng-repeat="l in list"></li>
</ul>
If you are trying to run something while your controller loads, it's actually much simpler than you thought:
app.controller('mainCtrl', function ($scope) {
var init = function ($scope) {
// do whatever you need to do to initialize your controller
$scope.someData = ["Hey", "I'm", "Alive"]
$scope.otherData = localStorage.getItem('myBackup')
}
init()
})
Or even simpler, if you don't need the function (no closures or whatever)
app.controller('mainCtrl', function ($scope) {
// do whatever you need to do to initialize your controller
$scope.someData = ["Hey", "I'm", "Alive"]
$scope.otherData = localStorage.getItem('myBackup')
})
Edit - assuming you're using ngView:
To have the code run on when the page is fully loaded you should set a watcher on the event $viewContentLoaded, like this:
$scope.$on('$viewContentLoaded', function(){
//Here your view content is fully loaded !!
});
app.controller('mainCtrl', function ($scope) {
// This event is triggered when the view has finished loading
$scope.$on('$viewContentLoaded', function() {
$scope.someData = ["Hey", "I'm", "Alive"]
$scope.otherData = localStorage.getItem('myBackup')
})
})
another option is using jquery. It would fit if you depend on many elements. But make sure to load jquery with a version of your choice to project.
loading jquery (insert version where it's ...):
<script src="https://code.jquery.com/jquery-..."></script>
the js code:
$(document).ready(function() {
alert("do something");
});
I have checked some of the topics for this matter and i got an understanding of controllers are there to initiate scope and i need to use services for this matter but i dont know how.
so here is the problem. i have index page which body has only one div and inside the div i have ng-include listening to a function called viewFile() which is described on controllerA. on the first initial attempt i load a view called login.html and display it. when users logs in and its successful, which are handled in controllerB, i return a token and now i want to load main.html page using viewFile() in controllerA. is there a call back function or notify controller or something for this? or can i write a service that takes care of this for me?
I'm not using ngRoute because i dont want my URL to change to mysite.com/#/login.html and then mysite.com/#/main.html
.controlle("A", function ($scope, sharedVariable){
$scope.token = sharedVariable.getToken();
$scope.viewFile = function(){
if($scope.token == "")
return "view/Login.html";
else
return "view/main.html";
}
}
.controller("B", function ($scope, $http, sharedVariable)){
http({
get ...
.success: function(data){
$scope.token = sharedVariable.setToken();
// INVOKE viewFile from above controller
}
})
}
and here is the index.html body part
<body>
<div ng-controller="A"><ng-include src="viewFile()"></ng-include></div>
</body>
look at this simple example http://jsfiddle.net/derkoe/T85rg/presentation/ here personService.person is shared between two controllers similarly you can write your viewFile function in one service like personService. Then call personService.viewFile from any controller. You can pass $scope as its argumen. Something like below
var myModule = angular.module('myModule', []);
myModule.factory('myService', function($rootScope) {
var sharedService = {};
sharedService.viewFile = function($scope) {
if($scope.token == "")
return "view/Login.html";
else
return "view/main.html";
};
return sharedService;
});
If you want to change the view using different condition define you viewFile function in some service or put it in routescope. Then you can call it from multiple controllers. But I don't think without refresh angularjs will be able to load a different view html