I have an issue with my angularjs app on the events and listeners.
My application has an index.html file like this:
<body ng-app="ua.myApp">
<!-- Navigation bar -->
<ng-include src="'app/common/navbar/navbar.tpl.html'"></ng-include>
<ng-view></ng-view>
<script type="text/javascript" src="app/common/navbar/navbar.js"></script>
<script type="text/javascript" src="app/part1/part1.js"></script>
</body>
In the navbar controller I have a listener:
console.log('Setup event listner - navBar: update');
$scope.$on('navBar: update', function() {
if (uaContext.loginStatus.get() == true) {
$scope.setLoggedInBar();
} else {
$scope.setLoggedOutBar();
}
});
And in the part1 app I broadcast an event:
function ($scope, $rootScope, $routeParams, uaContext) {
console.log('Send event listner - navBar: update');
$scope.$on('$routeChangeSuccess', function () {
uaContext.productId.set($routeParams.productId);
uaContext.appName.set('part 1');
$rootScope.$broadcast('navBar: update');
});
}
The dependencies in myApp are in this order:
var myApp = angular.module('ua.myApp', [
'ua.NavBar',
'ua.Part1']);
It's working fine. Console log:
Setup event listner - navBar: update (nav_bar.js)
Send event listner - navBar: update (part1.js)
The issue is that sometimes the event is sent by part1 app before the listener in navbar is operational. So we get this situation:
Send event listner - navBar: update (part1.js)
Setup event listner - navBar: update (nav_bar.js)
Thus the nav bar is not updated.
Do you know how I can fix this issue? Maybe I can emit the event in another event than routeChangeSuccess but I didn't found the documentation on the events.
Thank you
You can listen for the $includeContentLoaded event in the $scope that applies to where the ng-include is set.
Another solution, rather than relying on timing events, is to create a service that can be injected into both controllers which can be used to share navigation state between the two. That way, even if an event is fired before the navbar controller is instantiated, the navbar controller can read the appropriate state from the shared service.
Related
<template id="parentComp">
<child-comp-1 #customEvent="handler"/>
<child-comp-2 #customEvent="handler"/>
</template>
Since I receive the same event and use the same event handler for both events , is there a way to listen to them in common , ie can I make the event bubble up like native events and use something like
<template id="parentComp" #customEvent="handler">
Other than just passing the event to the parent you can use an event bus. This article describes this principle well: https://medium.com/#andrejsabrickis/https-medium-com-andrejsabrickis-create-simple-eventbus-to-communicate-between-vue-js-components-cdc11cd59860
The idea is to use a shared Vue instance to handle events. You will then import this instance in different elements, the same way you would import a library.
To listen from multiple components.
Emit and listen the event from root level
this.$root.$emit('myTestEvent',dataToBeSent);
Now you can listen from any component using
mounted(){
this.$root.$on('myTestEvent', (dataReceived) => {
//...
})
}
you can use $listeners for event bubbling. give you an example
Vue.component('inner-com',{
template: '<div>inner component<button #click="innerClick">emit event</button></div>',
methods: {
innerClick () {
this.$emit('inner-com-click-event');
}
}
})
Vue.component('middle-com',{
template: '<div>middle component<inner-com v-on="$listeners"></inner-com></div>'
})
Vue.component('outer-com',{
template: '<div>outer component<middle-com v-on="$listeners"></middle-com></div>'
})
var app = new Vue({
el:'#app',
methods: {
eventHandler () {
alert('event receved')
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<outer-com #inner-com-click-event="eventHandler"></outer-com>
</div>
I am trying to integrate Yammer share button https://developer.yammer.com/docs/share-button, I successfully implemented as instructed, but the only catch is first time it requires two click to fire up, later on single click seems to do the job. Here is the code below.
function clickSaveShare(){
var options = {
customButton : true, //false by default. Pass true if you are providing your own button to trigger the share popup
classSelector: 'homeBtn',//if customButton is true, you must pass the css class name of your button (so we can bind the click event for you)
defaultMessage: 'My custom Message', //optionally pass a message to prepopulate your post
pageUrl: 'www.microsoft.com' //current browser url is used by default. You can pass your own url if you want to generate the OG object from a different URL.
};
yam.platform.yammerShare(options);
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<span href="#" class="homeBtn" onclick="clickSaveShare(339,'Reverse KT')"> Click here to share</a>
<script>
</script>
<script type="text/javascript" src="https://s0.assets-yammer.com/assets/platform_social_buttons.min.js"></script>
<script type="text/javascript">yam.platform.yammerShare();</script>
</body>
</html>
Calling yam.platform.yammerShare() doesn't actually call the share to Yammer function despite its name. What it does is apply a click event to the specified DOM element so that when that element is clicked the Yammer popup will appear.
The reason you have to click the button twice is that the first time clickSaveShare is called, it calls yam.platform.yammerShare() which sets up a click event on the specified DOM element. The next time the button is clicked your click event has been replaced with the Yammer one so it works as expected.
One simple way to fix it given that you are including jQuery would be to use jQuery's document.ready event:
$(document).ready(function() {
var options = {
customButton : true,
classSelector: 'homeBtn',
defaultMessage: 'My custom Message',
pageUrl: 'www.microsoft.com'
};
yam.platform.yammerShare(options);
});
Here is a CodePen example of the above.
I'm new to polymer/webcomponents and I'm trying to set an attribute in a component but don't want the corresponding event to be fired.
Why? Because I want to be able to do two things:
1) When the control changes (by clicking on the checkbox) I want to use the event handler to send this event to a server (using websockets)
2) When the control should change (by an event via websocket) I want to be able to set the checkbox but not fire the event.
Hope I made my point clear. It's very hot in germany right now -> brain is melting ;)
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../paper-checkbox/paper-checkbox.html">
<polymer-element name="webmpc-player">
<template>
<paper-checkbox id="repeat" on-change={{change}}></paper-checkbox> Repeat
<paper-checkbox id="shuffle" on-change={{change}}></paper-checkbox> Shuffle
</template>
<script>
Polymer('webmpc-player', {
ready : function() {
/* Set the component property */
this.$.shuffle.checked = true;
},
change : function(e, detail, sender) {
alert('I don't want to be called!');
}
});
</script>
</polymer-element>
Thank you, this looks like a flaw in paper-checkbox.
I just posted an issue ticket to describe the problem.
https://github.com/Polymer/paper-checkbox/issues/9.
In socket.io, you can bind to a socket event/channel like this:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
But how do you stop listening to the "news" event?
Try, socket.removeAllListeners("news");
The off function can also be used.
socket.off('news'); // stops listening to the "news" event
socket.off('news', myFunction); // useful if you have multiple listeners for the same event
socket.off(); // stops listening to all events
Sources
According to the Socket.io Client Documentation "the socket actually inherits every method of the Emitter class, like hasListeners, once or off (to remove an event listener)."
Emitter documentation:
Pass event and fn to remove a listener.
Pass event to remove all listeners on that event.
Pass nothing to remove all listeners on all events.
If you want to remove only a specific event you can try socket.removeListener('you_event');
Is it possible to bind listeners to when an AJAX request is started in Can.JS? I want to integrate a little loading indicator in my Can.JS project so that users can see when data is being loaded from my server. Using the jQuery $.ajaxStart and $.ajaxSend events didn't work, however the $.ajaxComplete event did fire correctly.
In your example you are binding to the event on document.ready which is after you start the Ajax request. The complete log only shows because the document is ready and binds the event before the Ajax request returns. If you do everything in the correct order on document.ready like this:
$(document).ready(function(e){
$(document).ajaxStart(function(){
console.log('start');
}).ajaxComplete(function(){
console.log("Complete");
});
var TestModel = can.Model({
findAll: "GET http://jsfiddle.net/echo/json/"
});
TestModel.findAll({}, function(result){
alert(result);
});
});
It works as expected (see updated fiddle).