Browser Dialer with Node.js and AngularJS

This application allows you to make a phone call from your browser using Twilio Client.

It also includes a couple of other standard features you would expect a browser phone to have:

  1. Mute and unmute microphone input
  2. Send DTMF touch tones using the HTML keypad

Browser Dialer

This tutorial highlights the key bits of code that make this application work. Check out the project README on GitHub to see how to run the code yourself.

Creating a Twilio Application

This application requires a TwiML application to make a phone call, in this step we'll show you how to create it.

To create a TwiML App open you Console and click the button "Create new TwiML App".

New Twiml App

Every TwiML application needs a friendly name (we called ours “Browser Dialer”) and either a Voice URL or a Messaging URL. Since we want our users to make phone calls, we used a URL to our application’s “/voice” route.

Note: When running the app locally, you can use a tool like ngrok to get a publicly accessible URL for your development environment.

Loading Code Samples...
Language
'use strict';
require('dotenv-safe').load();
const http = require('http');
const express = require('express');
const {urlencoded} = require('body-parser');
const twilio = require('twilio');
const ClientCapability = twilio.jwt.ClientCapability;
const VoiceResponse = twilio.twiml.VoiceResponse;


const app = express();
app.use('/node_modules', express.static(__dirname + '/node_modules'));
app.use(express.static(__dirname + '/public'));
app.use(urlencoded({extended: false}));

// Generate a Twilio Client capability token
app.get('/token', (request, response) => {
  const capability = new ClientCapability({
    accountSid: process.env.TWILIO_ACCOUNT_SID,
    authToken: process.env.TWILIO_AUTH_TOKEN
  });

  capability.addScope(
    new ClientCapability.OutgoingClientScope({
      applicationSid: process.env.TWILIO_TWIML_APP_SID})
  );

  const token = capability.toJwt();

  // Include token in a JSON response
  response.send({
    token: token,
  });
});

// Create TwiML for outbound calls
app.post('/voice', (request, response) => {
  const voiceResponse = new VoiceResponse();
  voiceResponse.dial({
    callerId: process.env.TWILIO_NUMBER,
  }, request.body.number);

  response.type('text/xml');
  response.send(voiceResponse.toString());
});

const server = http.createServer(app);
const port = process.env.PORT || 3000;
server.listen(port, () => {
  console.log(`Express Server listening on *:${port}`);
});

module.exports = app;
index.js
The Main Application File

index.js

You've seen how to create the TwiML application. Next, let's learn how to generate a capability token so that our clients can make outbound calls.

Generate a Capability Token

Before our users can make any calls in their browsers, we need to create a capability token for them.

Capability tokens are your way to control exactly what your users can and can't do with Twilio Client. In this case, our server will provide all users with tokens that allow them to make outbound phone calls.

We use the Twilio Node Helper Library to generate and configure a capability token with the SID of our Twilio Application to allow outgoing calls.

Loading Code Samples...
Language
'use strict';
require('dotenv-safe').load();
const http = require('http');
const express = require('express');
const {urlencoded} = require('body-parser');
const twilio = require('twilio');
const ClientCapability = twilio.jwt.ClientCapability;
const VoiceResponse = twilio.twiml.VoiceResponse;


const app = express();
app.use('/node_modules', express.static(__dirname + '/node_modules'));
app.use(express.static(__dirname + '/public'));
app.use(urlencoded({extended: false}));

// Generate a Twilio Client capability token
app.get('/token', (request, response) => {
  const capability = new ClientCapability({
    accountSid: process.env.TWILIO_ACCOUNT_SID,
    authToken: process.env.TWILIO_AUTH_TOKEN
  });

  capability.addScope(
    new ClientCapability.OutgoingClientScope({
      applicationSid: process.env.TWILIO_TWIML_APP_SID})
  );

  const token = capability.toJwt();

  // Include token in a JSON response
  response.send({
    token: token,
  });
});

// Create TwiML for outbound calls
app.post('/voice', (request, response) => {
  const voiceResponse = new VoiceResponse();
  voiceResponse.dial({
    callerId: process.env.TWILIO_NUMBER,
  }, request.body.number);

  response.type('text/xml');
  response.send(voiceResponse.toString());
});

const server = http.createServer(app);
const port = process.env.PORT || 3000;
server.listen(port, () => {
  console.log(`Express Server listening on *:${port}`);
});

module.exports = app;
index.js
Token Generation Route

index.js

The Twilio.js client needs credentials to be able to initiate calls as well as send messages, among other cool features. The Twilio.js client requests the token from the /token route, at which point the client is initialized and ready to start using Twilio API's. Next, let's set up the Twilio Device in the browser.

Set Up the Twilio Device

In our client-side code, we start by including the Twilio.js library.

We then retrieve the capability token from the route /token with a POST request using jQuery.

Lastly, we pass our token to Twilio.Device.setup() to finish the setup.

The Twilio.Device.ready() callback is used to notify us when the device is ready to make calls.

Loading Code Samples...
Language
SDK Version:
  • component
(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'dialer-app',
      template: `
  <div id="dialer">
    <dialer-input (onChangeNumber)="handleChangeNumber($event)"></dialer-input>

    <audio-controls [onPhone]="onPhone" [muted]="muted" [disabled]="!isValidNumber"
        (onClickCall)="toggleCall()" (onClickMute)="toggleMute()"></audio-controls>

    <dtmf *ngIf="onPhone" (onDigitClick)="sendDigit($event)"></dtmf>

    <statuslog [status]="logtext" ></statuslog>

  </div>`
    })
    .Class({

      constructor: function() {
        this.onPhone = false;
        this.muted = false;
        this.isValidNumber = false;
      },

      ngOnInit: function() {
        var self = this;

        // Fetch Twilio capability token from our Node.js server
        $.getJSON('/token').done(function(data) {
          Twilio.Device.setup(data.token);
        }).fail(function(err) {
          console.log(err);
          self.logtext = 'Could not fetch token, see console.log';
        });

        // Configure event handlers for Twilio Device
        Twilio.Device.disconnect(function() {
          self.onPhone = false;
          self.logtext = 'Call ended.';
        });

        Twilio.Device.ready(function() {
          self.logtext = 'Connected';
        });
      },

      // Handle numeric buttons event
      sendDigit: function(digit) {
        Twilio.Device.activeConnection().sendDigits(digit);
      },

      // Handle number change event
      handleChangeNumber: function(event) {
        this.fullNumber = event.fullNumber;
        this.isValidNumber = event.isValid;
      },

      // Make an outbound call with the current number,
      // or hang up the current call
      toggleCall: function() {
        if (!this.onPhone) {
          this.onPhone = true;
          this.muted = false;

          Twilio.Device.connect({number: this.fullNumber});
          this.logtext = `Calling ${this.fullNumber}`;
        } else {
          // hang up call in progress
          Twilio.Device.disconnectAll();
        }

        Twilio.Device.ready(() => {
          self.log = 'Connected';
        });
      },

      // Handle muting
      toggleMute: function() {
        this.muted = !this.muted;
        Twilio.Device.activeConnection().mute(this.muted);
      },
    });
})(window.app || (window.app = {}));
public/app.component.js
Set Up the Twilio Device

public/app.component.js

Setting up the Twilio Device was easy since the /token route simplifies authorization. Now that the Twilio Client is initialized, let's see how to start an outbound call.

Make a Call

Now that the Twilio Client is ready, our users can start making phone calls. They'll start by inputting the phone number they wish to call.

We manage that input before passing the number on to Twilio, adding a + sign, then a country code, and the actual number. This is called the E.164 format and is required by most parts of Twilio's API.

We then use Twilio.Device.connect() to start the call. Twilio will send a request to the URL you specified in your Twilio Application configuration, looking for instructions on how to handle the call.

In this case, we include the phone number the user wishes to dial in our connect() call, and we then access it in our server-side code here.

Loading Code Samples...
Language
SDK Version:
  • component
(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'dialer-app',
      template: `
  <div id="dialer">
    <dialer-input (onChangeNumber)="handleChangeNumber($event)"></dialer-input>

    <audio-controls [onPhone]="onPhone" [muted]="muted" [disabled]="!isValidNumber"
        (onClickCall)="toggleCall()" (onClickMute)="toggleMute()"></audio-controls>

    <dtmf *ngIf="onPhone" (onDigitClick)="sendDigit($event)"></dtmf>

    <statuslog [status]="logtext" ></statuslog>

  </div>`
    })
    .Class({

      constructor: function() {
        this.onPhone = false;
        this.muted = false;
        this.isValidNumber = false;
      },

      ngOnInit: function() {
        var self = this;

        // Fetch Twilio capability token from our Node.js server
        $.getJSON('/token').done(function(data) {
          Twilio.Device.setup(data.token);
        }).fail(function(err) {
          console.log(err);
          self.logtext = 'Could not fetch token, see console.log';
        });

        // Configure event handlers for Twilio Device
        Twilio.Device.disconnect(function() {
          self.onPhone = false;
          self.logtext = 'Call ended.';
        });

        Twilio.Device.ready(function() {
          self.logtext = 'Connected';
        });
      },

      // Handle numeric buttons event
      sendDigit: function(digit) {
        Twilio.Device.activeConnection().sendDigits(digit);
      },

      // Handle number change event
      handleChangeNumber: function(event) {
        this.fullNumber = event.fullNumber;
        this.isValidNumber = event.isValid;
      },

      // Make an outbound call with the current number,
      // or hang up the current call
      toggleCall: function() {
        if (!this.onPhone) {
          this.onPhone = true;
          this.muted = false;

          Twilio.Device.connect({number: this.fullNumber});
          this.logtext = `Calling ${this.fullNumber}`;
        } else {
          // hang up call in progress
          Twilio.Device.disconnectAll();
        }

        Twilio.Device.ready(() => {
          self.log = 'Connected';
        });
      },

      // Handle muting
      toggleMute: function() {
        this.muted = !this.muted;
        Twilio.Device.activeConnection().mute(this.muted);
      },
    });
})(window.app || (window.app = {}));
public/app.component.js
Call Toggle

public/app.component.js

As you have seen, connecting and disconnecting from a call is quite simple. Next, we'll enable the client to mute and unmute active calls.

Mute and Unmute an Active Call

Sometimes you want to mute or unmute the current call, halting input from the user's microphone.

We can useTwilio.Device.activeConnection() to get the active call, and then call its mute() method to mute or unmute the user's microphone.

Loading Code Samples...
Language
SDK Version:
  • component
(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'dialer-app',
      template: `
  <div id="dialer">
    <dialer-input (onChangeNumber)="handleChangeNumber($event)"></dialer-input>

    <audio-controls [onPhone]="onPhone" [muted]="muted" [disabled]="!isValidNumber"
        (onClickCall)="toggleCall()" (onClickMute)="toggleMute()"></audio-controls>

    <dtmf *ngIf="onPhone" (onDigitClick)="sendDigit($event)"></dtmf>

    <statuslog [status]="logtext" ></statuslog>

  </div>`
    })
    .Class({

      constructor: function() {
        this.onPhone = false;
        this.muted = false;
        this.isValidNumber = false;
      },

      ngOnInit: function() {
        var self = this;

        // Fetch Twilio capability token from our Node.js server
        $.getJSON('/token').done(function(data) {
          Twilio.Device.setup(data.token);
        }).fail(function(err) {
          console.log(err);
          self.logtext = 'Could not fetch token, see console.log';
        });

        // Configure event handlers for Twilio Device
        Twilio.Device.disconnect(function() {
          self.onPhone = false;
          self.logtext = 'Call ended.';
        });

        Twilio.Device.ready(function() {
          self.logtext = 'Connected';
        });
      },

      // Handle numeric buttons event
      sendDigit: function(digit) {
        Twilio.Device.activeConnection().sendDigits(digit);
      },

      // Handle number change event
      handleChangeNumber: function(event) {
        this.fullNumber = event.fullNumber;
        this.isValidNumber = event.isValid;
      },

      // Make an outbound call with the current number,
      // or hang up the current call
      toggleCall: function() {
        if (!this.onPhone) {
          this.onPhone = true;
          this.muted = false;

          Twilio.Device.connect({number: this.fullNumber});
          this.logtext = `Calling ${this.fullNumber}`;
        } else {
          // hang up call in progress
          Twilio.Device.disconnectAll();
        }

        Twilio.Device.ready(() => {
          self.log = 'Connected';
        });
      },

      // Handle muting
      toggleMute: function() {
        this.muted = !this.muted;
        Twilio.Device.activeConnection().mute(this.muted);
      },
    });
})(window.app || (window.app = {}));
public/app.component.js
The Mute Toggle

public/app.component.js

Now you have an idea of how simple it is to use the Twilio Client in the browser. There are much more features to explore. Next, let's allow the user to send DTMF tones, in case they are calling an automated phone system.

Send DTMF Tones

If our user calls an automated phone system, they might need to navigate a menu system using our phone's keypad and DTMF tones.

DTMF stands for "Dual-tone multi-frequency signaling" and are the familiar sounds you hear when dialing a phone. DTMF have been standardized so they can be understood and decoded by machines.

To play DTMF tones with the Twilio.js client library we use the sendDigits method, passing which digit the user pressed as our sole argument.

Loading Code Samples...
Language
SDK Version:
  • component
(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'dialer-app',
      template: `
  <div id="dialer">
    <dialer-input (onChangeNumber)="handleChangeNumber($event)"></dialer-input>

    <audio-controls [onPhone]="onPhone" [muted]="muted" [disabled]="!isValidNumber"
        (onClickCall)="toggleCall()" (onClickMute)="toggleMute()"></audio-controls>

    <dtmf *ngIf="onPhone" (onDigitClick)="sendDigit($event)"></dtmf>

    <statuslog [status]="logtext" ></statuslog>

  </div>`
    })
    .Class({

      constructor: function() {
        this.onPhone = false;
        this.muted = false;
        this.isValidNumber = false;
      },

      ngOnInit: function() {
        var self = this;

        // Fetch Twilio capability token from our Node.js server
        $.getJSON('/token').done(function(data) {
          Twilio.Device.setup(data.token);
        }).fail(function(err) {
          console.log(err);
          self.logtext = 'Could not fetch token, see console.log';
        });

        // Configure event handlers for Twilio Device
        Twilio.Device.disconnect(function() {
          self.onPhone = false;
          self.logtext = 'Call ended.';
        });

        Twilio.Device.ready(function() {
          self.logtext = 'Connected';
        });
      },

      // Handle numeric buttons event
      sendDigit: function(digit) {
        Twilio.Device.activeConnection().sendDigits(digit);
      },

      // Handle number change event
      handleChangeNumber: function(event) {
        this.fullNumber = event.fullNumber;
        this.isValidNumber = event.isValid;
      },

      // Make an outbound call with the current number,
      // or hang up the current call
      toggleCall: function() {
        if (!this.onPhone) {
          this.onPhone = true;
          this.muted = false;

          Twilio.Device.connect({number: this.fullNumber});
          this.logtext = `Calling ${this.fullNumber}`;
        } else {
          // hang up call in progress
          Twilio.Device.disconnectAll();
        }

        Twilio.Device.ready(() => {
          self.log = 'Connected';
        });
      },

      // Handle muting
      toggleMute: function() {
        this.muted = !this.muted;
        Twilio.Device.activeConnection().mute(this.muted);
      },
    });
})(window.app || (window.app = {}));
public/app.component.js
Digit Input Handler

public/app.component.js

As you have seen, sending DTMF tones in response to button clicks is straightforward. Lastly our clients may want to hang up a call. Let's see how we can do that next.

Hang up the Call

Lastly, our users should be able to end a call.

To achieve this we use Twilio.Device.disconnectAll(), which terminates the current call.

Loading Code Samples...
Language
SDK Version:
  • component
(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'dialer-app',
      template: `
  <div id="dialer">
    <dialer-input (onChangeNumber)="handleChangeNumber($event)"></dialer-input>

    <audio-controls [onPhone]="onPhone" [muted]="muted" [disabled]="!isValidNumber"
        (onClickCall)="toggleCall()" (onClickMute)="toggleMute()"></audio-controls>

    <dtmf *ngIf="onPhone" (onDigitClick)="sendDigit($event)"></dtmf>

    <statuslog [status]="logtext" ></statuslog>

  </div>`
    })
    .Class({

      constructor: function() {
        this.onPhone = false;
        this.muted = false;
        this.isValidNumber = false;
      },

      ngOnInit: function() {
        var self = this;

        // Fetch Twilio capability token from our Node.js server
        $.getJSON('/token').done(function(data) {
          Twilio.Device.setup(data.token);
        }).fail(function(err) {
          console.log(err);
          self.logtext = 'Could not fetch token, see console.log';
        });

        // Configure event handlers for Twilio Device
        Twilio.Device.disconnect(function() {
          self.onPhone = false;
          self.logtext = 'Call ended.';
        });

        Twilio.Device.ready(function() {
          self.logtext = 'Connected';
        });
      },

      // Handle numeric buttons event
      sendDigit: function(digit) {
        Twilio.Device.activeConnection().sendDigits(digit);
      },

      // Handle number change event
      handleChangeNumber: function(event) {
        this.fullNumber = event.fullNumber;
        this.isValidNumber = event.isValid;
      },

      // Make an outbound call with the current number,
      // or hang up the current call
      toggleCall: function() {
        if (!this.onPhone) {
          this.onPhone = true;
          this.muted = false;

          Twilio.Device.connect({number: this.fullNumber});
          this.logtext = `Calling ${this.fullNumber}`;
        } else {
          // hang up call in progress
          Twilio.Device.disconnectAll();
        }

        Twilio.Device.ready(() => {
          self.log = 'Connected';
        });
      },

      // Handle muting
      toggleMute: function() {
        this.muted = !this.muted;
        Twilio.Device.activeConnection().mute(this.muted);
      },
    });
})(window.app || (window.app = {}));
public/app.component.js
Hang up Call

public/app.component.js

That's it! We crafted an application that allows our users to make browser-to-phone calls using Twilio.js.

Where to Next?

If you're a node developer working with Twilio, you might also enjoy these tutorials:

IVR: Phone Tree with Node.js and Express

Easily route callers to the right people and information with an IVR (interactive voice response) system.

Click to Call with Node.js and Express

Click-to-call enables your company to convert web traffic into phone calls with the click of a button.

Did this help?

Thanks for checking this tutorial out! If you have any feedback to share with us please contact us on Twitter, we'd love to hear it.

Agustin Camino
Hector Ortega
Jose Oliveros
David Prothero
Samuel Mendes

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
'use strict';
require('dotenv-safe').load();
const http = require('http');
const express = require('express');
const {urlencoded} = require('body-parser');
const twilio = require('twilio');
const ClientCapability = twilio.jwt.ClientCapability;
const VoiceResponse = twilio.twiml.VoiceResponse;


const app = express();
app.use('/node_modules', express.static(__dirname + '/node_modules'));
app.use(express.static(__dirname + '/public'));
app.use(urlencoded({extended: false}));

// Generate a Twilio Client capability token
app.get('/token', (request, response) => {
  const capability = new ClientCapability({
    accountSid: process.env.TWILIO_ACCOUNT_SID,
    authToken: process.env.TWILIO_AUTH_TOKEN
  });

  capability.addScope(
    new ClientCapability.OutgoingClientScope({
      applicationSid: process.env.TWILIO_TWIML_APP_SID})
  );

  const token = capability.toJwt();

  // Include token in a JSON response
  response.send({
    token: token,
  });
});

// Create TwiML for outbound calls
app.post('/voice', (request, response) => {
  const voiceResponse = new VoiceResponse();
  voiceResponse.dial({
    callerId: process.env.TWILIO_NUMBER,
  }, request.body.number);

  response.type('text/xml');
  response.send(voiceResponse.toString());
});

const server = http.createServer(app);
const port = process.env.PORT || 3000;
server.listen(port, () => {
  console.log(`Express Server listening on *:${port}`);
});

module.exports = app;
'use strict';
require('dotenv-safe').load();
const http = require('http');
const express = require('express');
const {urlencoded} = require('body-parser');
const twilio = require('twilio');
const ClientCapability = twilio.jwt.ClientCapability;
const VoiceResponse = twilio.twiml.VoiceResponse;


const app = express();
app.use('/node_modules', express.static(__dirname + '/node_modules'));
app.use(express.static(__dirname + '/public'));
app.use(urlencoded({extended: false}));

// Generate a Twilio Client capability token
app.get('/token', (request, response) => {
  const capability = new ClientCapability({
    accountSid: process.env.TWILIO_ACCOUNT_SID,
    authToken: process.env.TWILIO_AUTH_TOKEN
  });

  capability.addScope(
    new ClientCapability.OutgoingClientScope({
      applicationSid: process.env.TWILIO_TWIML_APP_SID})
  );

  const token = capability.toJwt();

  // Include token in a JSON response
  response.send({
    token: token,
  });
});

// Create TwiML for outbound calls
app.post('/voice', (request, response) => {
  const voiceResponse = new VoiceResponse();
  voiceResponse.dial({
    callerId: process.env.TWILIO_NUMBER,
  }, request.body.number);

  response.type('text/xml');
  response.send(voiceResponse.toString());
});

const server = http.createServer(app);
const port = process.env.PORT || 3000;
server.listen(port, () => {
  console.log(`Express Server listening on *:${port}`);
});

module.exports = app;
SDK Version:
  • component
(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'dialer-app',
      template: `
  <div id="dialer">
    <dialer-input (onChangeNumber)="handleChangeNumber($event)"></dialer-input>

    <audio-controls [onPhone]="onPhone" [muted]="muted" [disabled]="!isValidNumber"
        (onClickCall)="toggleCall()" (onClickMute)="toggleMute()"></audio-controls>

    <dtmf *ngIf="onPhone" (onDigitClick)="sendDigit($event)"></dtmf>

    <statuslog [status]="logtext" ></statuslog>

  </div>`
    })
    .Class({

      constructor: function() {
        this.onPhone = false;
        this.muted = false;
        this.isValidNumber = false;
      },

      ngOnInit: function() {
        var self = this;

        // Fetch Twilio capability token from our Node.js server
        $.getJSON('/token').done(function(data) {
          Twilio.Device.setup(data.token);
        }).fail(function(err) {
          console.log(err);
          self.logtext = 'Could not fetch token, see console.log';
        });

        // Configure event handlers for Twilio Device
        Twilio.Device.disconnect(function() {
          self.onPhone = false;
          self.logtext = 'Call ended.';
        });

        Twilio.Device.ready(function() {
          self.logtext = 'Connected';
        });
      },

      // Handle numeric buttons event
      sendDigit: function(digit) {
        Twilio.Device.activeConnection().sendDigits(digit);
      },

      // Handle number change event
      handleChangeNumber: function(event) {
        this.fullNumber = event.fullNumber;
        this.isValidNumber = event.isValid;
      },

      // Make an outbound call with the current number,
      // or hang up the current call
      toggleCall: function() {
        if (!this.onPhone) {
          this.onPhone = true;
          this.muted = false;

          Twilio.Device.connect({number: this.fullNumber});
          this.logtext = `Calling ${this.fullNumber}`;
        } else {
          // hang up call in progress
          Twilio.Device.disconnectAll();
        }

        Twilio.Device.ready(() => {
          self.log = 'Connected';
        });
      },

      // Handle muting
      toggleMute: function() {
        this.muted = !this.muted;
        Twilio.Device.activeConnection().mute(this.muted);
      },
    });
})(window.app || (window.app = {}));
SDK Version:
  • component
(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'dialer-app',
      template: `
  <div id="dialer">
    <dialer-input (onChangeNumber)="handleChangeNumber($event)"></dialer-input>

    <audio-controls [onPhone]="onPhone" [muted]="muted" [disabled]="!isValidNumber"
        (onClickCall)="toggleCall()" (onClickMute)="toggleMute()"></audio-controls>

    <dtmf *ngIf="onPhone" (onDigitClick)="sendDigit($event)"></dtmf>

    <statuslog [status]="logtext" ></statuslog>

  </div>`
    })
    .Class({

      constructor: function() {
        this.onPhone = false;
        this.muted = false;
        this.isValidNumber = false;
      },

      ngOnInit: function() {
        var self = this;

        // Fetch Twilio capability token from our Node.js server
        $.getJSON('/token').done(function(data) {
          Twilio.Device.setup(data.token);
        }).fail(function(err) {
          console.log(err);
          self.logtext = 'Could not fetch token, see console.log';
        });

        // Configure event handlers for Twilio Device
        Twilio.Device.disconnect(function() {
          self.onPhone = false;
          self.logtext = 'Call ended.';
        });

        Twilio.Device.ready(function() {
          self.logtext = 'Connected';
        });
      },

      // Handle numeric buttons event
      sendDigit: function(digit) {
        Twilio.Device.activeConnection().sendDigits(digit);
      },

      // Handle number change event
      handleChangeNumber: function(event) {
        this.fullNumber = event.fullNumber;
        this.isValidNumber = event.isValid;
      },

      // Make an outbound call with the current number,
      // or hang up the current call
      toggleCall: function() {
        if (!this.onPhone) {
          this.onPhone = true;
          this.muted = false;

          Twilio.Device.connect({number: this.fullNumber});
          this.logtext = `Calling ${this.fullNumber}`;
        } else {
          // hang up call in progress
          Twilio.Device.disconnectAll();
        }

        Twilio.Device.ready(() => {
          self.log = 'Connected';
        });
      },

      // Handle muting
      toggleMute: function() {
        this.muted = !this.muted;
        Twilio.Device.activeConnection().mute(this.muted);
      },
    });
})(window.app || (window.app = {}));
SDK Version:
  • component
(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'dialer-app',
      template: `
  <div id="dialer">
    <dialer-input (onChangeNumber)="handleChangeNumber($event)"></dialer-input>

    <audio-controls [onPhone]="onPhone" [muted]="muted" [disabled]="!isValidNumber"
        (onClickCall)="toggleCall()" (onClickMute)="toggleMute()"></audio-controls>

    <dtmf *ngIf="onPhone" (onDigitClick)="sendDigit($event)"></dtmf>

    <statuslog [status]="logtext" ></statuslog>

  </div>`
    })
    .Class({

      constructor: function() {
        this.onPhone = false;
        this.muted = false;
        this.isValidNumber = false;
      },

      ngOnInit: function() {
        var self = this;

        // Fetch Twilio capability token from our Node.js server
        $.getJSON('/token').done(function(data) {
          Twilio.Device.setup(data.token);
        }).fail(function(err) {
          console.log(err);
          self.logtext = 'Could not fetch token, see console.log';
        });

        // Configure event handlers for Twilio Device
        Twilio.Device.disconnect(function() {
          self.onPhone = false;
          self.logtext = 'Call ended.';
        });

        Twilio.Device.ready(function() {
          self.logtext = 'Connected';
        });
      },

      // Handle numeric buttons event
      sendDigit: function(digit) {
        Twilio.Device.activeConnection().sendDigits(digit);
      },

      // Handle number change event
      handleChangeNumber: function(event) {
        this.fullNumber = event.fullNumber;
        this.isValidNumber = event.isValid;
      },

      // Make an outbound call with the current number,
      // or hang up the current call
      toggleCall: function() {
        if (!this.onPhone) {
          this.onPhone = true;
          this.muted = false;

          Twilio.Device.connect({number: this.fullNumber});
          this.logtext = `Calling ${this.fullNumber}`;
        } else {
          // hang up call in progress
          Twilio.Device.disconnectAll();
        }

        Twilio.Device.ready(() => {
          self.log = 'Connected';
        });
      },

      // Handle muting
      toggleMute: function() {
        this.muted = !this.muted;
        Twilio.Device.activeConnection().mute(this.muted);
      },
    });
})(window.app || (window.app = {}));
SDK Version:
  • component
(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'dialer-app',
      template: `
  <div id="dialer">
    <dialer-input (onChangeNumber)="handleChangeNumber($event)"></dialer-input>

    <audio-controls [onPhone]="onPhone" [muted]="muted" [disabled]="!isValidNumber"
        (onClickCall)="toggleCall()" (onClickMute)="toggleMute()"></audio-controls>

    <dtmf *ngIf="onPhone" (onDigitClick)="sendDigit($event)"></dtmf>

    <statuslog [status]="logtext" ></statuslog>

  </div>`
    })
    .Class({

      constructor: function() {
        this.onPhone = false;
        this.muted = false;
        this.isValidNumber = false;
      },

      ngOnInit: function() {
        var self = this;

        // Fetch Twilio capability token from our Node.js server
        $.getJSON('/token').done(function(data) {
          Twilio.Device.setup(data.token);
        }).fail(function(err) {
          console.log(err);
          self.logtext = 'Could not fetch token, see console.log';
        });

        // Configure event handlers for Twilio Device
        Twilio.Device.disconnect(function() {
          self.onPhone = false;
          self.logtext = 'Call ended.';
        });

        Twilio.Device.ready(function() {
          self.logtext = 'Connected';
        });
      },

      // Handle numeric buttons event
      sendDigit: function(digit) {
        Twilio.Device.activeConnection().sendDigits(digit);
      },

      // Handle number change event
      handleChangeNumber: function(event) {
        this.fullNumber = event.fullNumber;
        this.isValidNumber = event.isValid;
      },

      // Make an outbound call with the current number,
      // or hang up the current call
      toggleCall: function() {
        if (!this.onPhone) {
          this.onPhone = true;
          this.muted = false;

          Twilio.Device.connect({number: this.fullNumber});
          this.logtext = `Calling ${this.fullNumber}`;
        } else {
          // hang up call in progress
          Twilio.Device.disconnectAll();
        }

        Twilio.Device.ready(() => {
          self.log = 'Connected';
        });
      },

      // Handle muting
      toggleMute: function() {
        this.muted = !this.muted;
        Twilio.Device.activeConnection().mute(this.muted);
      },
    });
})(window.app || (window.app = {}));
SDK Version:
  • component
(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'dialer-app',
      template: `
  <div id="dialer">
    <dialer-input (onChangeNumber)="handleChangeNumber($event)"></dialer-input>

    <audio-controls [onPhone]="onPhone" [muted]="muted" [disabled]="!isValidNumber"
        (onClickCall)="toggleCall()" (onClickMute)="toggleMute()"></audio-controls>

    <dtmf *ngIf="onPhone" (onDigitClick)="sendDigit($event)"></dtmf>

    <statuslog [status]="logtext" ></statuslog>

  </div>`
    })
    .Class({

      constructor: function() {
        this.onPhone = false;
        this.muted = false;
        this.isValidNumber = false;
      },

      ngOnInit: function() {
        var self = this;

        // Fetch Twilio capability token from our Node.js server
        $.getJSON('/token').done(function(data) {
          Twilio.Device.setup(data.token);
        }).fail(function(err) {
          console.log(err);
          self.logtext = 'Could not fetch token, see console.log';
        });

        // Configure event handlers for Twilio Device
        Twilio.Device.disconnect(function() {
          self.onPhone = false;
          self.logtext = 'Call ended.';
        });

        Twilio.Device.ready(function() {
          self.logtext = 'Connected';
        });
      },

      // Handle numeric buttons event
      sendDigit: function(digit) {
        Twilio.Device.activeConnection().sendDigits(digit);
      },

      // Handle number change event
      handleChangeNumber: function(event) {
        this.fullNumber = event.fullNumber;
        this.isValidNumber = event.isValid;
      },

      // Make an outbound call with the current number,
      // or hang up the current call
      toggleCall: function() {
        if (!this.onPhone) {
          this.onPhone = true;
          this.muted = false;

          Twilio.Device.connect({number: this.fullNumber});
          this.logtext = `Calling ${this.fullNumber}`;
        } else {
          // hang up call in progress
          Twilio.Device.disconnectAll();
        }

        Twilio.Device.ready(() => {
          self.log = 'Connected';
        });
      },

      // Handle muting
      toggleMute: function() {
        this.muted = !this.muted;
        Twilio.Device.activeConnection().mute(this.muted);
      },
    });
})(window.app || (window.app = {}));