Listen for a specific $includeContentLoaded - angularjs

$includeContentLoaded is fired every time ngInclude is updated.
$scope.$on('$includeContentLoaded', function() {
// Emitted every time the ngInclude content is reloaded
});
What I would like to do, is to listen for a specific ngInclude to be loaded, like a callback:
$scope.includePath('/path/to/iclude', function() {
// Fired when the includePath ngInclude have finished loading
}
Is this possible?

You can use "onload" tag:
<div ng-include="url" onload="test(url)">
</div>
And check url in scope function, for example:
$scope.test = function(url){
switch(url) {
case '/path/to/iclude':
/*******YOUR CODE***********/
break;
}
}

in Angular 1.3, you have:
$rootScope.$on('$includeContentLoaded',function(event,url){
if (url == 'YourDesiredPath') {
// do something
}
});

Angular has its own method : $includeContentLoaded
$scope.$on('$includeContentLoaded', function(eve,uri) {
if(uri == 'views/templates/sample.html'){
// do something
});
}

Related

Watcher not firing when contents of object changes

Why is my $interval visibly refreshing the model?
I'm trying to automatically update the song that I'm playing right now and showing it on my website. For that, I used the $interval function. The problem is that the model (div) is refreshing every 10 seconds, while I want it only to refresh when the song changes (and just checking every 10 seconds)
I tried changing the $interval function with setInterval(), but no luck.
angular.module('lastfm-nowplaying', [])
.directive('lastfmnowplaying', ['uiCreation', 'lastFmAPI', 'lastFmParser', '$interval', function(uiCreation, lastFmAPI, lastFmParser, $interval){
var link = function(scope, element, attrs){
scope.$watch('config', function(value) {
load();
});
var load = function(){
function SongCheck(){
var latestTrack;
if (scope.config){
if (scope.config.apiKey){
lastFmAPI.getLatestScrobbles(scope.config)
.then(function(data){
latestTrack = lastFmParser.getLatestTrack(data);
angular.element(element).addClass('lastfm-nowplaying');
uiCreation.create(element[0], scope.config.containerClass, latestTrack);
}, function(reason) {
//Last.fm failure
});
}
else{
var latestTrack = {
title: scope.config.title,
artist: scope.config.artist,
largeImgUrl: scope.config.imgUrl,
xLargeImgUrl: scope.config.backgroundImgUrl,
}
angular.element(element).addClass('lastfm-nowplaying');
uiCreation.create(element[0], scope.config.containerClass, latestTrack);
}
}
}
SongCheck();
$interval(function () {
SongCheck();
} , 8000);
}
};
return {
scope:{
config: '=config'
},
link: link
};
}])
The code works, but I want the model to change when a change is detected (in this case the json file).
Watcher not firing when contents of object changes
Delete the $interval timer and use the "deep watch" version of the watcher:
scope.$watch('config', function(value) {
load(value);
̶}̶)̶;̶
}, true);
Normally the watcher only fires when the object reference changes. Set the second argument to true to have the watcher fire when the object contents changes.
For more information, see
AngularJS Developer Guide - Scope $watch depths

Angular Directive not updating element using interval

i have this directive
angular.module('mydirectives').directive('slideShow', function ($interval) {
return{
scope:{slideShow:'=slideShow'},
link:function(scope, element, attrs){
element.css("background-size","cover");
element.css("background-repeat","none");
element.css("background-position","center center");
element.css("background-blend-mode","color");
element.css("background-color","rgba(0, 0, 0, 0.5)");
scope.index=0;
function nextSlide()
{
if(!scope.slideShow) return;
if(scope.slideShow.sources.length===0) return;
var url=scope.slideShow.sources[scope.index++];
if(scope.index>=scope.slideShow.sources.length) scope.index=0;
element.css({'background-image': 'url(' + url +')'});
}
nextSlide();
var interval= $interval(nextSlide,3000)
scope.$on("$destroy",function(){
$interval.cancel(interval);
})
}
}
});
this is how i apply it
<section class="primary" slide-show="slideShow">
now the controller which provides property "slideShow" gets the value via http request. when it comes back with response it sets the value of slideShow like this
$scope.slideShow={sources:["http:\\sources\someimage.jgp"]}
webApi.getHomePageModel().then(function(model){
$scope.model=model;
$scope.slideShow=model.slideShow;
},function(error){
console.dir(error);
});
The Problem: when this runs only the default value of slideshow works and element's background-image is set but after the response to http the new value is set to slideShow but the when interval function "nextSlide" executes then background-image is not updated. in debugger i can see the url values is being picked up correctly but element is not updated.
EDIT:I was making a stupid mistake, the updated model was not as expected the elements in sources were not strings as expected (they were being generated as complex objects rather than string value.) all working now. also no need for scope.$applyAsync because the $interval service handles that for you
If you are using setInterval then you need to manually rerun angular's digetst cycle:
function nextSlide()
{
if(!scope.slideShow) return;
if(scope.slideShow.sources.length===0) return;
var url=scope.slideShow.sources[scope.index++];
if(scope.index>=scope.slideShow.sources.length) scope.index=0;
element.css({'background-image': 'url(' + url +')'});
scope.applyAsync(); //this line!
//May not work in older angular versions, if such you should use scope.apply()
}
I got it working with this implementation
angular.module('app').directive('slideShow', function ($interval) {
return{
scope:{slideShow:'=slideShow'},
link:function(scope, element, attrs){
var index=0;
function nextSlide()
{
if(!scope.slideShow) return;
if(scope.slideShow.images.length===0) return;
var url=scope.slideShow.images[index++];
if(index>=scope.slideShow.images.length) index=0;
element.css({'background-image': 'url(' + url +')'});
}
var interval=false;
var watchSlideShow=scope.$watch("slideShow",function(){
if(!scope.slideShow) return;
if(scope.slideShow.images.length===0) return;
if(interval) return;
nextSlide();
var interval= $interval(nextSlide,5000);
});
scope.$on("$destroy",function(){
$interval.cancel(interval);
watchSlideShow();
});
}
}
});

Get vis.js networkEvents from the controller

I need to use click event in my controller.
The networkEvents are created in angular-vs.js directive and I need it in my controller to trigger the click event of individual nodes.
This is a code snippet I'm using but it does seem to work:
$scope.networkEvents = { onload:function(network){ alert("Clicked"); } }
Thanks,
Here is my plunker.
index.html
It looks like you don't set your events attribute of the vis-network directive, so I think you meant:
<vis-network data="data" options="options" events="networkEvents" height="100%"></vis-network>
angular-vis.js
Also, in the onload callback of the vis-network directive (line 151) you're passing graph into the onload function, but it isn't defined. (Maybe it's supposed to be network instead?):
// onLoad callback
if (scope.events != null && scope.events.onload != null &&
angular.isFunction(scope.events.onload)) {
scope.events.onload(network);
}
script.js
With the above changes, the onload function seems to work as expected. Since you've already set up the forEach loop to attach the events, to get the click event you just need to add it to the networkEvents object:
$scope.networkEvents =
{
onload: function(network){
alert("I'm loaded");
},
click: function(clicked) {
alert("id: " + clicked.nodes[0] + " was clicked");
}
}

Dynamically added element's directive doesn't work

I'm trying to build a simple infinite scroll. It loads the data fine but after loading, new added elements' directives don't work.
This is relevant part of the scroll checking and data loading directive.
.directive("scrollCheck", function ($window, $http) {
return function(scope, element, attrs) {
angular.element($window).bind("scroll", function() {
// calculating windowBottom and docHeight here then
if (windowBottom >= (docHeight - 100)) {
// doing some work here then
$http.get('service page').then(function (result) {
if (result.data.trim() != "") {
var newDiv = angular.element(result.data);
element.append(newDiv);
}
// doing some other work
},function () {
// error handling here
});
}
scope.$apply();
});
};
})
Service page returns some repeats of this structure as result.data
<div ...>
<div ... ng-click="test($event)"></div>
<div ...>...</div>
</div>
As i said data loads just fine but those test() functions in ng-clickdirectives don't work. How to get em work?
I believe you are going to need to compile the html element returned. Something like this
$compile(newDiv)(scope); // Corrected. Thanks
You'll need to be sure and pass in $compile into your function

How to check internet connection in AngularJs

This is how I would check internet connection in vanilla javascript:
setInterval(function(){
if(navigator.onLine){
$("body").html("Connected.");
}else{
$("body").html("Not connected.");
}
},1000);
I have angular controllers and modules in my project. Where should I put the code above? It should be executed in global context and not be assigned to a certain controller. Are there some kind of global controllers maybe?
First of all, I advise you to listen to online/offline events.
You can do it this way in AnguarJS:
var app = module('yourApp', []);
app.run(function($window, $rootScope) {
$rootScope.online = navigator.onLine;
$window.addEventListener("offline", function() {
$rootScope.$apply(function() {
$rootScope.online = false;
});
}, false);
$window.addEventListener("online", function() {
$rootScope.$apply(function() {
$rootScope.online = true;
});
}, false);
});
NOTE: I am wrapping changing of root scope's variable in $apply method to notify Angular that something was changed.
After that you can:
In controlller:
$scope.$watch('online', function(newStatus) { ... });
In HTML markup:
<div ng-show="online">You're online</div>
<div ng-hide="online">You're offline</div>
Here is a working Plunker: http://plnkr.co/edit/Q3LkiI7Cj4RWBNRLEJUA?p=preview
Other solution could be to broadcast online/offline event. But in this case you need to initialize current status upon loading and then subscribe to event.
It's definitely not as nice, but you could just try an AJAX request to your web server; it'll either succeed or time out.
Also, the HubSpot/offline project looks really good.
Your options:
addEventListener on the window, document, or document.body.
setting the .ononline or .onoffline properties on document or
document.body to a JavaScript Function object.
specifying ononline="..." or onoffline="..." attributes on the tag in
the HTML markup
I will demonstrate the easiest.
In you controller
document.body.onoffline = function() {
alert('You are offline now');
$scope.connection = 'offline'
}
document.body.ononline = function() {
alert('You are online again');
$scope.connection = 'online'
}
Check $scope.connection variable before you try to send requests around.
For Angular 2+ you can use ng-speed-test:
Just install:
npm install ng-speed-test --save
Inject into your module:
import { SpeedTestModule } from 'ng-speed-test';
#NgModule({
...
imports: [
SpeedTestModule,
...
],
...
})
export class AppModule {}
Use service to get speed:
import {SpeedTestService} from 'ng-speed-test';
#Injectable()
export class TechCheckService {
constructor(
private speedTestService:SpeedTestService
) {
this.speedTestService.getMbps().subscribe(
(speed) => {
console.log('Your speed is ' + speed);
}
);
}
}

Resources