pubnub / pubnub-angular

Official PubNub AngularJS SDK
Other
84 stars 43 forks source link

PubNub AngularJS SDK

SDK Logo

Build Status Codecov npm Bower

Welcome! We're here to get you started quickly with your integration between PubNub and AngularJS. PubNub makes it easy to integrate real-time bidirectional communication into your app.

Pubnub Angular service is a wrapper for PubNub JavaScript SDK version 4 and version 3 that adds a few of extra features to simplify Angular integrations:

You can still use the native PubNub JavaScript SDK if you feel this will be more suitable for your situation.

For more information, visit our docs page.

Communication

Breaking changes

Integrating PubNub AngularJS SDK into Your App

Your HTML page will include 2 key libraries:

1. To install the PubNub AngularJS SDK:

bower install --save pubnub pubnub-angular

npm install --save pubnub pubnub-angular

<script src="http(s)://cdn.pubnub.com/sdk/pubnub-angular/pubnub-angular-4.2.0.js"></script>
<script src="http(s)://cdn.pubnub.com/sdk/pubnub-angular/pubnub-angular-4.2.0.min.js"></script>

To utilize this wrapper, include the scripts in the following order:

  <script src="https://github.com/pubnub/pubnub-angular/raw/master/(angular.js)"></script>
  <script src="https://github.com/pubnub/pubnub-angular/raw/master/(latest version of PubNub JS SDK from https://github.com/pubnub/javascript)"></script>
  <script src="https://github.com/pubnub/pubnub-angular/raw/master/(pubnub-angular.js)"></script>

We presume your app is already Angular-enabled with an ng-app attribute or the equivalent:

<body ng-app="PubNubAngularApp">

Where 'PubNubAngularApp' is the name of the Angular module containing your app.

We presume the code for the app lives in:

<script src="https://github.com/pubnub/pubnub-angular/raw/master/scripts/app.js"></script>

Inside app.js, add an Angular dependency on the PubNub Angular library (pubnub.angular.service):

angular.module('PubNubAngularApp', ["pubnub.angular.service"])

This will make sure that the PubNub object is available to get injected into your controllers.

We presume the code for your controllers lives in:

<script src="https://github.com/pubnub/pubnub-angular/raw/master/scripts/controllers/main.js"></script>

The Angular Pubnub service is injected into the controller as follows:

.controller('MainCtrl', function($scope, Pubnub) { ... });

Differences in usage with native JavaScript SDK

In Pubnub AngularJS SDK instances are hidden inside service and are accessible via instance getter.

Creating a default instance

PubNub AngularJS SDK with JS V4 PubNub AngularJS SDK with JS V3
Javascript SDK
var defaultInstance = new PubNub({
    publishKey: 'your pub key',
    subscribeKey: 'your sub key'
});
var defaultInstance = PUBNUB.init({
    publish_key: 'your pub key',
    subscribe_key: 'your sub key'
});
PubNub AngularJS SDK
Pubnub.init({
    publishKey: 'your pub key',
    subscribeKey: 'your sub key'
});
Pubnub.init({
    publish_key: 'your pub key',
    subscribe_key: 'your sub key'
});

Creating an other instance

In most use cases, usage of the default PubNub instance will be sufficient, but if multiple instances with different credentials are needed, the Pubnub.getInstance(instanceName) getter needs to be utilized.

PubNub AngularJS SDK with JS V4 PubNub AngularJS SDK with JS V3
PubNub AngularJS SDK
Pubnub.getInstance("another").init({
    publishKey: 'your pub key',
    subscribeKey: 'your sub key'
});
Pubnub.getInstance("another").init({
    publish_key: 'your pub key',
    subscribe_key: 'your sub key'
});

Accessing methods

All methods of the Native Javascript SDKs are wrapped within the Pubnub AngularJS Service.

To learn about PubNub JavaScript features and methods available refer to the API Reference of the Javascript SDK that you are using:

Examples:

PubNub AngularJS SDK with JS V4 PubNub AngularJS SDK with JS V3
With the default instance
Pubnub.publish({
    channel: 'myChannel',
    message: 'Hello!'
  }, function(status, response){
       console.log(response);
});
Pubnub.publish({
    channel: 'myChannel',
    message: 'Hello!',
    callback: function (m) {console.log(m);},
    error: function (err) {console.log(err);}
});
With an other instance
Pubnub.getInstance("another").publish({
    channel: 'myChannel',
    message: 'Hello!'
  }, function(status, response){
       console.log(response);
});
Pubnub.getInstance("another").publish({
    channel: 'myChannel',
    message: 'Hello!',
    callback: function (m) {console.log(m);}
});

That's it - you're ready to start using the AngularJS PubNub SDK!

Events

Another key feature of this SDK is the ability to trigger method events in addition to passed in callbacks. By default events will not be triggered.

To enable all possible events for certain method, add triggerEvents: true option to the method arguments.

Triggering and listening to events for the subscribe method

With Javascript V4, you can trigger 3 different events (message, presence and status)

Triggering the events:

Pubnub.subscribe({
    channels  : [$scope.selectedChannel],
    channelGroups: [$scope.selectedChannelGroup],
    withPresence: true,
    triggerEvents: ['message', 'presence', 'status']
  });
};

You can also enable all possible events using triggerEvents: true

Listening to a message event of a specific channel or channel group:

$rootScope.$on(Pubnub.getMessageEventNameFor($scope.selectedChannel), function (ngEvent, envelope) {
    $scope.$apply(function () {
        // add message to the messages list
        $scope.chatMessages.unshift(envelope.message);
    });
});

Listening to a presence event of a specific channel or channel group:

$rootScope.$on(Pubnub.getPresenceEventNameFor($scope.selectedChannel), function (ngEvent, pnEvent) {
        // apply presence event (join|leave) on users list
        handlePresenceEvent(pnEvent);
});

Listening to the global status events:

Via the status listener, you can receive different events such as when the network is online (PNNetworkUpCategory), when the SDK is connected to a set of channels (PNConnectedCategory), etc... See the list of events available in the API Reference

$rootScope.$on(Pubnub.getEventNameFor('subscribe', 'status'), function (ngEvent, status, response) {
    if (status.category == 'PNConnectedCategory'){
        console.log('successfully connected to channels', response);
    }
});

With PubNub Javascript V3, you can trigger 6 different events (callback, connect, reconnect,disconnect, error, presence)

Triggering the events:

Pubnub.subscribe({
    channel  : $scope.selectedChannel,
    channel_group: $scope.selectedChannelGroup,
    triggerEvents: ['callback', 'presence', 'connect', 'reconnect', 'disconnect', 'error']
  });

You can also enable all possible events using triggerEvents: true

Listening to a message event of a specific channel or channel group:

$rootScope.$on(Pubnub.getMessageEventNameFor($scope.selectedChannel), function (ngEvent, message, envelope, channel) {
        // add message to the messages list
        $scope.chatMessages.unshift(message);
});

Listening to a presence event of a specific channel or channel group:

$rootScope.$on(Pubnub.getPresenceEventNameFor($scope.selectedChannel), function (ngEvent, pnEvent, envelope, channel) {
     // apply presence event (join|leave) on users list
     handlePresenceEvent(pnEvent);
});

Listening to the other events (connect, reconnect, disconnect and error)

$rootScope.$on(Pubnub.getEventNameFor('subscribe', 'connect'), function (ngEvent, payload) {
        $scope.statusSentSuccessfully = true;
});

And so on for the connect, reconnect, disconnect and error event.

Triggering and listening to events for the methods with callbacks

You have the possibility to trigger events for the methods with callbacks.

For the required callbacks, for ex. the callback called callback in the publish method, you should add it using one of the following ways:

Triggering the events:

PubNub AngularJS SDK with JS v4 PubNub AngularJS SDK with JS v3
Method with callbacks as argument
Pubnub.publish({
    channel: 'myChannel',
    message: 'Hello!'
  }, function(status, response){
       console.log(response);
});
Pubnub.publish({
    channel: 'myChannel',
    message: 'Hello!',
    callback: function (m) {console.log(m);},
    error: function(err) {console.log(err);}
});
Method with events triggered
Pubnub.publish({
    channel: 'myChannel',
    message: 'Hello!',
    triggerEvents: ['callback']
  }
Pubnub.publish({
    channel: 'myChannel',
    message: 'Hello!',
    triggerEvents: ['callback', 'error']
});

Listening to the events:

You can listen to the events that have been triggered using the Pubnub.getEventNameFor(...) helper from anywhere in your app. Params order in broadcasted events is the same as in native SDK methods, except that ngEvent object is prepended as the first param.

With JS V4 the callback event will be triggered for both successful and unsuccesfull response:

$rootScope.$on(Pubnub.getEventNameFor('publish', 'callback'),
  function (ngEvent, status, response) {
    $scope.$apply(function () {
        if (status.error){
           $scope.statusSentSuccessfully = false;
        } else {
           $scope.statusSentSuccessfully = true;
        }
     })
});

With JS V3 you will get the successful and unsuccessful responses as two separate events (callback and error):

$rootScope.$on(Pubnub.getEventNameFor('publish', 'callback'),
  function (ngEvent, payload) {
    $scope.$apply(function () {
        $scope.statusSentSuccessfully = true;
    });
});
$rootScope.$on(Pubnub.getEventNameFor('publish', 'error'),
  function (ngEvent, payload) {
    $scope.$apply(function () {
        $scope.statusSentSuccessfully = false;
    });
});

The $pubnubChannel object

The $pubnubChannel object allows you to seamlessly bind a PubNub channel to a scope variable, which gets automatically updated when there is new realtime data published in that channel. It also lets you interact directly with the channel by calling dedicated methods available into the $scope variable bound to the $pubnubChannel object.

Getting started

Init Pubnub:

With JS V4 With JS V3
Pubnub.init({
    publishKey: 'your pub key',
    subscribeKey: 'your sub key'
});
Pubnub.init({
    publish_key: 'your pub key',
    subscribe_key: 'your sub key'
});

Inject the $pubnubChannel service in a controller:

.controller('ScoresCtrl', function($scope, $pubnubChannel) { ... });

Bind the $pubnubChannel object to a scope variable providing a channel name and some optional parameters:

.controller('ScoresCtrl', function($scope, $pubnubChannel) {

  $scope.scores = $pubnubChannel('game-scores-channel',{ autoload: 50 })

});

Instantiating the $pubnubChannel is the only step needed to have a scope variable that reflects the realtime data from a channel. It subscribes to the channel for you, load initial data if needed and receive new realtime data automatically.

Display the $scope.scores variable in your view and you will see the data beeing loaded and updated when new data is received in that channel:

<body ng-app="app" ng-controller="ScoresCtrl">
   <ul class="collection">
     <li ng-repeat="score in scores">{{score.player}}<li>
   </ul>
</body>

Optional config parameters:

You can pass in some optional parameters in the config hash when instantiating the $pubnubChannel:

$scope.scores = $pubnubChannel('game-scores-channel', config)

Available methods

You can interact with the $pubnubChannel via dedicated methods:

.controller('ScoresCtrl', function($scope, $pubnubChannel) {

  $scope.scores = $pubnubChannel('game-scores-channel',{ autoload: 20 })
  $scope.scores.$publish({player: 'John', result: 32}) // Publish a message in the game-scores-channel channel.
});

Here are some methods you can use:

Wrapping the $pubnubChannel object in a Service.

Instead of using the $pubnubChannel directly in a controller you can wrap it into a Service:

app.factory("Scores", ["$pubnubChannel", function($pubnubChannel) {

    var config = {
                    instance: 'myAnotherPubNubInstanceName', // By default, the default PubNub instance
                    autoload: 50 // Autoload the channel with 50 messages (should be < 100)
                 }
    return $pubnubChannel('game-scores-channel', config);
  }
]);

And use the Scores service in a controller:

app.controller("ScoresCtrl", ["$scope", "Scores", function($scope, Scores) {
  $scope.messages = Scores();
]);

Extending the $pubnubChannel object

You can also extend the $pubnubChannel object using the $extend method in order to add or override methods:

angular.module('app')
.factory('Scores', ['$pubnubChannel',function ScoresService($pubnubChannel) {

    // We create an extended $pubnubChannel channel object that add a additionnal sendScore method
    // that publish a score with the name of the player preloaded.
    var Scores = $pubnubChannel.$extend({
      sendScore: function(score) {
         return this.$publish({
                                   player: 'John',
                                   score: score
                              })
         }
    });

   return Scores('game-scores-channel', {autoload: 30});

}]);

You can then use the Scores service in a controller:

app.controller("ScoresCtrl", ["$scope", "Scores", function($scope, Scores) {
  $scope.scores = Scores();
  $scope.scores.sendScore(34);
]);

The $pubnubChannelGroup object

The $pubnubChannelGroup provides an easy-to-use interface for channel groups. It stores the incoming messages in containers split by the channel and exposes an interface to directly fetch messages by channel using the $channel(channelName) method.

Getting started

Init Pubnub:

With JS V4 With JS V3
Pubnub.init({
    publishKey: 'your pub key',
    subscribeKey: 'your sub key'
});
Pubnub.init({
    publish_key: 'your pub key',
    subscribe_key: 'your sub key'
});

Inject the $pubnubChannelGroup service in a controller:

.controller('ChatCtrl', function($scope, $pubnubChannelGroup) { ... });

Instantiate a $pubnubChannelGroup object and assign it to a scope variable providing a channel group name and some optional parameters.

.controller('ChatCtrl', function($scope, $pubnubChannelGroup) {

  $scope.Conversations = $pubnubChannelGroup('conversations-channel-group')
  // Fetch a $pubnubChannel from the Conversations $pubnubChannelGroup object
  $scope.currentConversation = $scope.Conversations.$channel('conversation-178')
  // $scope.messages is a $pubnubChannel, you can use any method available for a $pubnubChannel
  $scope.currentConversation.$load(20)
});

Optional config parameters:

You can pass in some optional parameters in the config hash when instantiating the $pubnubChannelGroup:

$scope.Conversation = $pubnubChannelGroup('conversations-channel-group', config)

Methods available:

Wrapping the $pubnubChannelGroup object in a Service.

Instead of using the $pubnubChannelGroup directly in a controller you can wrap it into a Service:

app.factory("Conversations", ["$pubnubChannelGroup", function($pubnubChannelGroup) {
    return $pubnubChannelGroup('conversations-channel-group');
  }
]);

And use the Conversation service in a controller:

app.controller("ChatCtrl", ["$scope", "Conversation", function($scope, Conversation) {
   $scope.currentConversation = Conversations.$channel('conversation-13345');
]);

Extending channels of a $pubnubChannelGroup

When instanciating a $pubnubChannelGroup, you can pass in a channelExtension parameter that allows you to add or overrides methods for the $pubnubChannel objects that is returned when calling the $channel(channelName) method.

app.controller("ChatCtrl", ["$scope","$pubnubChannelGroup", function($scope, $pubnubChannelGroup) {

   // We add a sendMessage methods that publish a message with an already defined payload.
   var channelExtension = {
      sendMessage: function(messageContent) {
         return this.$publish({ content: messageContent, sender: "Tomomi" })
      }
   }
    $scope.Conversations = $pubnubChannelGroup('channelGroup', {channelExtension: channelExtension});
    $scope.currentConversation = $scope.Conversations.$channel('conversation-123')
    // Sending a message via the extra method added to the channel.
    $scope.currentConversation.sendMessage('Hello!')

]);

Contributing

To start the development environment by running npm install and bower install.