i am new in angular js. i done with div hide and show. just i want to know how to hide or show div for 3 seconds only.
here i attaching my code which i used.
html code:
<div ng-hide="loginAlertMessage">Dynamic user feedback message comes here.</div>
<a ng-click="forgotPassword()">Forgot Password?</a>
angular js code:
$scope.loginAlertMessage = true;
$scope.forgotPassword = function () {
$scope.loginAlertMessage=false;
};
Inject the $timeout service in the controller and use it to unset loginAlertMessage.
app.controller('MyController', ['$scope', '$timeout', function($scope, $timeout) {
$scope.loginAlertMessage = true;
$scope.forgotPassword = function() {
$scope.loginAlertMessage = false;
$timeout(function() {
$scope.loginAlertMessage = true;
}, 3000);
};
// ...
}]);
inject $timeout service (derived from setTimeout(function() {"action",time(in ms) }) in controller and if wish to display make the div true and if wish to hide make use this service to stop.
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 believe I am experiencing the same issue mentioned here: $anchorScroll and $location only work after second try
I reviewed the plunker that works and I have routing in place, but it is still taking two clicks. I am using ng-route and not ui-router. How can I prevent it taking two clicks to get anchorScroll to work? As the first wants to cause a route to be established versus scrolling to the appropriate anchor.
Here is the click:
<a data-ng-click="gotoRequests()">Requests</a>
Here is the destination:
<div id="pendingrequests"></div>
Here is the function in my controller:
$scope.gotoRequests = function() {
// set the location.hash to the id of
// the element you wish to scroll to.
$location.hash('pendingrequests');
// call $anchorScroll()
$anchorScroll();
};
I was able to solve it using one of the answers here: How to handle anchor hash linking in AngularJS
by creating the following function:
$scope.scrollTo = function(id) {
var old = $location.hash();
$location.hash(id);
$anchorScroll();
//reset to old to keep any additional routing logic from kicking in
$location.hash(old);
};
I would call this as follows:
Yipee
<div id="pendingrequests"></div>
Latest Update
From AngularJS 1.4.0 $anchorScroll allows you to directly pass the id as a parameter without the need to update the URL with the hash.
During click
<div data-ng-click="gotoRequests(pendingrequests)"> </div>
In Controller
$scope.gotoRequests = function(divId) { $anchorScroll(divId); }
I also had the same issue with angular 1 and I solved it using $timeout. Here is an example of how I did it
angular.module('app').controller('MyTestController', ['$scope', '$location', '$anchorScroll', '$timeout', function($scope, $location, $anchorScroll, $timeout) {
function scrollToElement (element, offset){
$timeout(function() {
$anchorScroll.yOffset = offset; // add extra pixels to scroll initially
var old = $location.hash();
$location.hash(element);
$anchorScroll();
$location.hash(old);
});
}
scrollToElement('element ID', 100);
}]);
You need to add $timer for 300 like:
this.gotoBottom = function(scrollId) {
$timeout(function() {
$location.hash(scrollId); $anchorScroll(scrollId);
}, 300);
}
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 a function which I want to call after page content is loaded. I read about $viewContentLoaded and it doesn't work for me. I am looking for something like
document.addEventListener('DOMContentLoaded', function () {
//Content goes here
}, false);
Above call doesn't work for me in AngularJs controller.
According to documentation of $viewContentLoaded, it supposed to work
Emitted every time the ngView content is reloaded.
$viewContentLoaded event is emitted that means to receive this event you need a parent controller like
<div ng-controller="MainCtrl">
<div ng-view></div>
</div>
From MainCtrl you can listen the event
$scope.$on('$viewContentLoaded', function(){
//Here your view content is fully loaded !!
});
Check the Demo
Angular < 1.6.X
angular.element(document).ready(function () {
console.log('page loading completed');
});
Angular >= 1.6.X
angular.element(function () {
console.log('page loading completed');
});
fixed - 2015.06.09
Use a directive and the angular element ready method like so:
js
.directive( 'elemReady', function( $parse ) {
return {
restrict: 'A',
link: function( $scope, elem, attrs ) {
elem.ready(function(){
$scope.$apply(function(){
var func = $parse(attrs.elemReady);
func($scope);
})
})
}
}
})
html
<div elem-ready="someMethod()"></div>
or for those using controller-as syntax...
<div elem-ready="vm.someMethod()"></div>
The benefit of this is that you can be as broad or granular w/ your UI as you like and you are removing DOM logic from your controllers. I would argue this is the recommended Angular way.
You may need to prioritize this directive in case you have other directives operating on the same node.
You can directly call it by adding {{YourFunction()}} after HTML element.
Here is a Plunker Link.
I had to implement this logic while handling with google charts. what i did was that at the end of my html inside controller definition i added.
<body>
-- some html here --
--and at the end or where ever you want --
<div ng-init="FunCall()"></div>
</body>
and in that function simply call your logic.
$scope.FunCall = function () {
alert("Called");
}
var myM = angular.module('data-module');
myM.directive('myDirect',['$document', function( $document ){
function link( scope , element , attrs ){
element.ready( function(){
} );
scope.$on( '$viewContentLoaded' , function(){
console.log(" ===> Called on View Load ") ;
} );
}
return {
link: link
};
}] );
Above method worked for me
you can call javascript version of onload event in angular js. this ng-load event can be applied to any dom element like div, span, body, iframe, img etc. following is the link to add ng-load in your existing project.
download ng-load for angular js
Following is example for iframe, once it is loaded testCallbackFunction will be called in controller
EXAMPLE
JS
// include the `ngLoad` module
var app = angular.module('myApp', ['ngLoad']);
app.controller('myCtrl', function($scope) {
$scope.testCallbackFunction = function() {
//TODO : Things to do once Element is loaded
};
});
HTML
<div ng-app='myApp' ng-controller='myCtrl'>
<iframe src="test.html" ng-load callback="testCallbackFunction()">
</div>
If you're getting a $digest already in progress error, this might help:
return {
restrict: 'A',
link: function( $scope, elem, attrs ) {
elem.ready(function(){
if(!$scope.$$phase) {
$scope.$apply(function(){
var func = $parse(attrs.elemReady);
func($scope);
})
}
else {
var func = $parse(attrs.elemReady);
func($scope);
}
})
}
}
I was using {{myFunction()}} in the template but then found another way here using $timeout inside the controller. Thought I'd share it, works great for me.
angular.module('myApp').controller('myCtrl', ['$timeout',
function($timeout) {
var self = this;
self.controllerFunction = function () { alert('controller function');}
$timeout(function () {
var vanillaFunction = function () { alert('vanilla function'); }();
self.controllerFunction();
});
}]);
Running after the page load should partially be satisfied by setting an event listener to the window load event
window.addEventListener("load",function()...)
Inside the module.run(function()...) of angular you will have all access to the module structure and dependencies.
You can broadcast and emit events for communications bridges.
For example:
module set onload event and build logic
module broadcast event to controllers when logic required it
controllers will listen and execute their own logic based on module onload processes.
If you want certain element to completely loaded, Use ng-init on that element .
e.g. <div class="modal fade" id="modalFacultyInfo" role="dialog" ng-init="initModalFacultyInfo()"> ..</div>
the initModalFacultyInfo() function should exist in the controller.
I found that if you have nested views - $viewContentLoaded gets triggered for every of the nested views. I've created this workaround to find the final $viewContentLoaded. Seems to work alright for setting $window.prerenderReady as required by Prerender (goes into .run() in the main app.js):
// Trigger $window.prerenderReady once page is stable
// Note that since we have nested views - $viewContentLoaded is fired multiple
// times and we need to go around this problem
var viewContentLoads = 0;
var checkReady = function(previousContentLoads) {
var currentContentLoads = Number(viewContentLoads) + 0; // Create a local copy of the number of loads
if (previousContentLoads === currentContentLoads) { // Check if we are in a steady state
$window.prerenderReady = true; // Raise the flag saying we are ready
} else {
if ($window.prerenderReady || currentContentLoads > 20) return; // Runaway check
$timeout(function() {checkReady(currentContentLoads);}, 100); // Wait 100ms and recheck
}
};
$rootScope.$on('$stateChangeSuccess', function() {
checkReady(-1); // Changed the state - ready to listen for end of render
});
$rootScope.$on('$viewContentLoaded', function() {
viewContentLoads ++;
});
var myTestApp = angular.module("myTestApp", []);
myTestApp.controller("myTestController", function($scope, $window) {
$window.onload = function() {
alert("is called on page load.");
};
});
The solution that work for me is the following
app.directive('onFinishRender', ['$timeout', '$parse', function ($timeout, $parse) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
if (!!attr.onFinishRender) {
$parse(attr.onFinishRender)(scope);
}
});
}
if (!!attr.onStartRender) {
if (scope.$first === true) {
$timeout(function () {
scope.$emit('ngRepeatStarted');
if (!!attr.onStartRender) {
$parse(attr.onStartRender)(scope);
}
});
}
}
}
}
}]);
Controller code is the following
$scope.crearTooltip = function () {
$('[data-toggle="popover"]').popover();
}
Html code is the following
<tr ng-repeat="item in $data" on-finish-render="crearTooltip()">
I use setInterval to wait for the content loaded. I hope this can help you to solve that problem.
var $audio = $('#audio');
var src = $audio.attr('src');
var a;
a = window.setInterval(function(){
src = $audio.attr('src');
if(src != undefined){
window.clearInterval(a);
$('audio').mediaelementplayer({
audioWidth: '100%'
});
}
}, 0);
I'm trying to show a no internet access button when my app user is not connected to the internet and the object in question is not available from the cache.
HTML:
<div class="VideoPlayerController video-player-controller">
<span class="icon-stack disconnected" ng-show="connectionError">
<icon type="signal" class="signal-icon"></icon>
<icon type="plus" class="plus-icon icon-stack-base"></icon>
</span>
<video autoplay controls></video>
JS:
(function() {
'use strict';
angular.module('core-viewer')
.controller('VideoPlayerController', ['$scope', 'ApiService', '$routeParams', 'NavbarService',
function($scope, ApiService, $routeParams, NavbarService) {
$scope.connectionError = false;
$scope.videoLoaded = function(video) {
NavbarService.header = video.title;
$('.video-player-controller video').bind("error", function(event) {
loadFail();
});
$('.video-player-controller video').attr('src', video.file.downloadURL);
};
function loadFail() {
if (!navigator.onLine) {
$scope.connectionError = true;
}
}
ApiService.getVideo($routeParams.uuid).then($scope.videoLoaded);
}]);
})();
Whenever connectionError gets set to true nothing happens back on the HTML view. It's obviously connecting in some way because if the default value of $scope.connectionError is false then it will hide the item, and if the default is true then it will show the item, but when the value is actually changed I see no response.
Am I missing something simple?
Whenever you make changes from outside of the angular framework, e.g. from browser DOM events, setTimeout, XHR or third party libraries, you need to use $apply as per the documentation.
function loadFail() {
if (!navigator.onLine) {
$scope.$apply(function() {
$scope.connectionError = true;
});
}
}
Edit:
You are doing a number of things considered bad practice, e.g. doing DOM manipulation inside your controller. I recommend you start from this answer.