emGee Software Solutions Custom Database Applications

Share this

Tuts+ Code - Web Development

Updated: 5 days 3 hours ago

How to Download Files in Python

Thu, 01/11/2018 - 04:00

Python provides several ways to download files from the internet. This can be done over HTTP using the urllib package or the requests library. This tutorial will discuss how to use these libraries to download files from URLs using Python.

REQUESTS

The requests library is one of the most popular libraries in Python. Requests allow you to send  HTTP/1.1 requests without the need to manually add query strings to your URLs, or form-encode your POST data.

With the requests library, you can perform a lot of functions including:

  • adding form data,
  • adding multipart files,
  • and accessing the response data of Python
MAKING REQUESTS

The first you need to do is to install the library and it's as simple as:

pip install requests

To test if the installation has been successful, you can do a very easy test in your  python interpreter by simply typing:

import requests

If the installation has been successful, there will be no errors.

HTTP requests include:

  • GET
  • POST
  • PUT
  • DELETE
  • OPTIONS
  • HEAD
Making a GET request

Making requests is very easy as illustrated below.

import requests req = requests.get(“http://www.google.com”)

The above command will get the google web page and store the information in thereq variable. We can then go on to get other attributes as well.

For instance, to know if fetching the google web page was successful, we will query the status_code.

import requests req = requests.get(“http://www.google.com") req.status_code 200 # 200 means a successful request

What if we want to find out the encoding type of the Google web page?

req.encoding ISO-8859–1

You might also want to know the contents of the response.

req.text

This is just a truncated content of the response.

'<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en "><head><meta content="Search the world\'s information, including webpages, imag es, videos and more. Google has many special features to help you find exactly w hat you\'re looking for." name="description"><meta content="noodp" name="robots" ><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta conten t="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image "><title>Google</title><script>(function(){window.google={kEI:\'_Oq7WZT-LIf28QWvMaking a POST Request

In simple terms, a POST request used to create or update data. This is especially used in the submission of forms.

Let's assume you have a registration form that takes an email address and password as input data, when you click on the submit button for registration, the post request will be as shown below.

data = {"email":"info@tutsplus.com", "password":"12345") req = requests.post(“http://www.google.com, params = data)Making a PUT Request

A PUT request is similar to a POST request. Its used to update data.For instance, the API below shows how to do a PUT request.

data= {"name":"tutsplus", "telephone":"12345") r.put("http://www.contact.com, params= data")Making a DELETE Request

A DELETE request, like the name suggests, is used to delete data. Below is an example of a DELETE request

data= {'name':'Tutsplus'} url = "https://www.contact.com/api/") response = requests.delete(url, params= data) urllib Package

urllib is a package that collects several modules for working with URLs namely:

urllib.request  offers a very simple interface, in the form of the urlopen function capable of fetching URLs using a variety of different protocols. It also offers a slightly more complex interface for handling basic authentication, cookies, proxies e.t. c.

How to Fetch URLs With urllib

The simplest way to use urllib.request is as follows:

import urllib.request with urllib.request.urlopen('http://python.org/') as response: html = response.read()

If you wish to retrieve an internet resource and store it, you can do so via the urlretrieve() function.

import urllib.request filename, headers = urllib.request.urlretrieve('http://python.org/') html = open(filename) Downloading Images With Python

In this example, we want to download the image available on this link using both the request llibrary and urllib module. 

url = 'https://www.python.org/static/opengraph-icon-200x200.png' # downloading with urllib # imported the urllib library import urllib # Copy a network object to a local file urllib.urlretrieve(url, "python.png") # downloading with requests # import the requests library import requests # download the url contents in binary format r = requests.get(url) # open method to open a file on your system and write the contents with open("python1.png", "wb") as code: code.write(r.content) Download PDF Files With Python

In this example, we will download a pdf about google trends from this link.

url = 'https://static.googleusercontent.com/media/www.google.com/en//googleblogs/pdfs/google_predicting_the_present.pdf' # downloading with urllib # import the urllib package import urllib # Copy a network object to a local file urllib.urlretrieve(url, "tutorial.pdf") # downloading with requests # import the requests library import requests # download the file contents in binary format r = requests.get(url) # open method to open a file on your system and write the contents with open("tutorial1.pdf", "wb") as code: code.write(r.content) Download Zip Files With Python

In this example, we are going to download the contents of a GitHub repository found in this link and store the file locally.

url = 'https://codeload.github.com/fogleman/Minecraft/zip/master' # downloading with requests # import the requests library import requests # download the file contents in binary format r = requests.get(url) # open method to open a file on your system and write the contents with open("minemaster1.zip", "wb") as code: code.write(r.content) # downloading with urllib # import the urllib library import urllib # Copy a network object to a local file urllib.urlretrieve(url, "minemaster.zip") Download Videos With Python

In this example, we want to download  the video lecture available on this page

url = 'https://www.youtube.com/watch?v=aDwCCUfNFug' video_name = url.split('/')[-1] # using requests # imported the requests library import requests print "Downloading file:%s" % video_name # download the url contents in binary format r = requests.get(url) # open method to open a file on your system and write the contents with open('tutorial.mp4', 'wb') as f: f.write(r.content) # using urllib # imported the urllib library import urllib print "Downloading file:%s" % video_name # Copy a network object to a local file urllib.urlretrieve(url, "tutorial2.mp4") Conclusion

This tutorial has covered the most commonly used methods to download files as well as the most common file formats. Even though you will write less code  when using  the urllib module, the requests module is preferred due to its simplicity, popularity and a wide array of features including:

  • Keep-Alive & Connection Pooling
  • International Domains and URLs
  • Sessions with Cookie Persistence
  • Browser-style SSL Verification
  • Automatic Content Decoding
  • Basic/Digest Authentication
  • Elegant Key/Value Cookies
  • Automatic Decompression
  • Unicode Response Bodies
  • HTTP(S) Proxy Support
  • Multipart File Uploads
  • Streaming Downloads
  • Connection Timeouts
  • Chunked Requests
  • .netrc Support

Categories: Web Design

10 Best WordPress Star Rating Plugins

Mon, 01/08/2018 - 04:00

The power of the star.

Not one. Not two. How about five?

That'd be great.

The five-star rating system is one that says so much, so quickly. Browsing movies, products, comments? No matter. A quick glance at a rating is a great way to communicate.

So why not add it to your blog comments, digital downloads, product sales, or media reviews?

You can easily add a WordPress star rating plugin to your website—no matter what you're interested in allowing users to rate.

Dive into these 10 best WordPress star rating plugins and see if you can find your five-star solution.

1. Product Category Rating

Easily boast about your five-star reviews using widgets and shortcodes with the Product Category Rating plugin.

The widget is an easy drag and drop with filters, and shortcodes can easily be configured using the built-in shortcode generator.

"The average rating of the product category is calculated based on each review rating received by the product."

Features also include:

  • custom post type and multisite support
  • support and detailed documentation
  • translation ready
  • and more

Between the easy shortcode generator and built-in widgets, you can easily add WordPress star ratings to your website with the Product Category Rating plugin.

2. Rating Form

If customization is your thing, then look no further for your WordPress star rating plugin—give Rating Form a try.

"Choose or create a Rating Form, choice of Stars, Hearts, Smileys, Thumbs Up & Down and many more or upload your own shapes. Lots of features and still expanding."

Transform those five-star rating reviews into something that matches your website perfectly and jumps off the page. Choose to: 

  • upload your own image
  • change the colors
  • size
  • the list goes on

But visual options are just the beginning.

Rating Form includes all the options you want in a WordPress star rating plugin—and more!

3. Five-Star Ratings & Reviews - WP Rating Plugin for Blogs, Review Sites and E-Commerce Shops

From blog comments to full-featured eCommerce websites, the Five-Star Ratings & Reviews - WP Rating Plugin for Blogs, Review Sites and E-Commerce Shops lets website users rate and review just about any kind of website content.

This WordPress star rating plugin supports:

  • Easy Digital Downloads
  • WP eCommerce
  • WooCommerce
  • and more!

Easily customize your rating icons and enjoy great features like:

  • allowing 1 person to vote based on IP address
  • online shop or marketplace integration
  • Custom Post Type support
  • and more

The Five-Star Ratings & Reviews - WP Rating Plugin for Blogs, Review Sites and E-Commerce Shops plugin is... five stars.

4. WordPress Rate Everything Star Rating Plugin

When five stars aren't enough, you need the WordPress Rate Everything Star Rating Plugin.

Not only does this WordPress star rating plugin work with WooCommerce, it works with any WordPress post, post type, and page. You can even drop it in using a short-code or add it directly to your theme.

Features include:

  • customize the number of stars
  • list in grid/list view and detailed view
  • integrate into all post types or only those specified
  • a different number of stars can be displayed based on display view
  • and more

One of the best features is the vote count system, allowing logged-in users to use AJAX. This makes WordPress Rate Everything Star Rating Plugin a "simple yet powerful rating solution with industry-leading accuracy in displaying decimal ratings."

5. Sama Author Review WordPress Plugin

The Sama Author Review WordPress Plugin is one of the more noteworthy designs in the WordPress star rating plugin space.

Features include:

  • allowing any user to leave a rating or only those logged in
  • supports Schema for Google Rich Snippet
  • three custom widgets and WPML support

And includes three different styles:

  1. Stars
  2. Points
  3. Percentages

With its unique design, the Sama Author Review WordPress Plugin is worth your attention.

6. WooCommerce Product Star Rating and Review

This is a WordPress star rating plugin made for WooCommerce. The WooCommerce Product Star Rating and Review makes it super easy to allow shoppers to leave reviews for your products—but only products that have been purchased by the customer.

"WooCommerce Product Star Rating and Review plugin is built to encourage customers to add lovely star ratings & reviews to your products, and make it extremely easy to do so."

Using the WooCommerce Product Star Rating and Review plugin adds features that customers would expect to find on big eCommerce sites.

7. Contact Form 7 Star Rating Field

Here's the perfect WordPress star rating plugin for those of you using Contact Form 7.

The Contact Form 7 Star Rating Field brings 12 different rating styles to the Star Rating field for one of the most popular contact forms for WordPress.

Like other Contact Form 7 fields, you have the option to set up your star rating to be required or not. You can use shortcodes to include the rating result in email, set a default rating, and much, much more.

Check it out. The Contact Form 7 Star Rating Field is a solid option.

8. Gravity Forms Star Rating Field

Easily add a star rating (or thumbs up, hearts, smiley faces, etc.) to your Gravity Form with the Gravity Forms Star Rating Field.

"Choose from 14 different rating style and set some setting options for your rating field."

Features include:

  • customize and show current rating on hover
  • customize and show rating text on the tooltip
  • and more

If you're using Gravity Forms, you'll want to use the Gravity Forms Star Rating Field.

9. Ninja Forms - Unique Fields

The Ninja Forms solution for a star rating is far more robust than any other listed thus far, when using the Ninja Forms - Unique Fields.

While it includes a star rating, it includes many other unique fields.

Additional unique fields include:

  • select, number
  • email, phone, date
  • address, city, zip, state, country
  • and more

And each field gets uniqueness settings, frontend validation, and more.

The Ninja Forms - Unique Fields is a must-have for any Ninja Forms user.

10. User Rating / Review Add on for UserPro

The User Rating / Review Add on for UserPro is a special WordPress star rating plugin specifically built for UserPro—a user profile and community plugin.

Features include:

  • ability to rate both users using star ratings or using text comments
  • adjust rating restrictions based on user role
  • shortcode and translation support
  • and more

Easily add star ratings to your UserPro community with the User Rating / Review Add on for UserPro plugin.

Conclusion

The Envato Market offers a great variety of WordPress themes and WordPress plugins, and their five-star star WordPress star rating plugins do not disappoint.

Adding the power of star ratings to your eCommerce site, digital downloads, contact forms, and comment sections has never been so easy.

If you still haven't found exactly what you're looking for, you'll want to check out Envato Tuts+. They have excellent WordPress tutorials, eBooks, and courses. You might try the WordPress Plugin Development Essentials or maybe the WordPress Hacker's Guide to the Galaxy. If you prefer eBooks, then Useful Tricks and Techniques for WordPress and Mastering WordPress are options you'll want to look at.

Categories: Web Design

Handling Forms in Vue.js

Tue, 01/02/2018 - 04:00
Introduction

When building web applications, there is always the possibility of working with forms. Learning to handle them as you work with different tools is very important. In this tutorial, you will see how to handle forms in Vue.js.

Get Started

Create a new Vue project using Vue-CLI. If you do not have Vue-CLI installed on your machine, you can do so by running:

npm install -g vue-cli

That will install Vue-CLI globally on your machine. You can go ahead to create the project by running:

vue init webpack vue-forms

That will create a new Vue project, using the Webpack template. Navigate to the directory that was created for the project, and install the dependencies.

cd vue-forms npm install

You will be making use of Bootstrap in this tutorial. Open your index.html file and make it look like this.

#index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>vue-forms</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"></head> <body> <div id="app"> </div> <script src="/dist/build.js"></script> </body> </html>

Nothing fancy here—just the link element tag for our Bootstrap stylesheet. You will build a simple registration form from scratch, and bind the values entered into the form using v-model. When working with forms in Vue.js, you bind form input values to the Vue instance using the v-model directive.

Input Binding

Let's get started with some simple text input to collect the email address, password, and age of the user. Open up your App.vue file.

Edit the template section to look like what I have below.

#src/App.vue <template> <div class="container"> <form> <div class="row"> <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3"> <h1>Enter your information</h1> <hr> <div class="form-group"> <label for="email">Mail</label> <input type="text" id="email" class="form-control" v-model="userData.email"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" id="password" class="form-control" v-model="userData.password"> </div> <div class="form-group"> <label for="age">Age</label> <input type="number" id="age" class="form-control" v-model="userData.age"> </div> </div> </div> </form> </div> </template>

In the above, you are using the v-model directive to bind the inputs for email, password, and age to an object. Here, the object is called userData. The userData object is supposed to have different properties—email, password and age—where the values of the inputs will be saved.

The userData object has to be defined in the data option of your Vue instance.

<script> export default { data () { return { userData: { email: '', password: '', age: 40 } } } } </script>

With that, you have established a two-way binding. You can now access the values for the email, password, and age inputs as userData.email, userData.password, and userData.age respectively. From the above, you set the default value for the age object. Without entering a value, the value is set at 40. This is an example of how you can implement defaults when working with forms in Vue.js.

Input Modifiers

Now go to the form group for your password to make the password visible. The form group should look like this.

<div class="form-group"> <label for="password">Password</label> <input type="password" id="password" class="form-control" v-model="userData.password"> <p>{{ userData.password }}</p> </div>

As you enter inputs in the input box, each letter you enter gets displayed. Vue.js gives you the option to halt display of the values till you move to another input field or another place in the page. To do this, you have to edit the v-model directive by adding a lazy modifier, like so.

<input type="password" id="password" class="form-control" v-model.lazy="userData.password">

This does not listen to the input event, but the change event that gets fired when you are done with that input field. Another modifier that can come handy is the trim modifier. If used for the email field, it will look like this.

<input type="text" id="email" class="form-control" v-model.trim="userData.email">

This is the same way you used the lazy modifier. The trim modifier will remove any extra space from the entered values.

Working with textarea is like what you did above. The only difference is that interpolation will not work. Let's add a textarea to our form, inside the form tag.

<div class="row"> <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 form-group"> <label for="message">Message</label><br> <!-- Interpolation between <textarea>{{ test }}</textarea> doesn't work!--> <textarea id="message" rows="5" class="form-control" v-model="message"></textarea> </div> </div>

Update the model to look like this.

<script> export default { data () { return { userData: { email: '', password: '', age: 40 }, message: 'This is a placeholder text' } } } </script>Checkboxes and Radio Buttons

Checkboxes give users the opportunity to select more than one option. When implementing this, the values are bound to the same array.

So, in your template, you should add this.

<div class="row"> <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3"> <div class="form-group"> <label for="designer"> <input type="checkbox" id="designer" value="Designer" v-model="occupation"> Designer </label> <label for="developer"> <input type="checkbox" id="developer" value="developer" v-model="occupation"> Developer </label><!-- Also show for single checkbox with true/ false --> </div> </div> </div>

While the data model is updated too.

data () { return { userData: { email: '', password: '', age: 40 }, message: 'This is a placeholder text', occupation: [] } }

If you are working with radio buttons, where the user can only select one option, you do not make use of an array. Let's add radio buttons to the registration form.

<div class="row"> <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 form-group"> <label for="male"> <input type="radio" id="male" value="Male" v-model="gender"> Male </label> <label for="female"> <input type="radio" id="female" value="Female" v-model="gender"> Female </label> </div> </div>

The corresponding data model will look like this.

data () { return { userData: { email: '', password: '', age: 40 }, message: 'This is a placeholder text', occupation: [], gender: 'Female } }

Vue.js knows that both radio buttons belong to the same group, so it only allows the selection of one. It also stores the value of the selected radio button in the gender property; this is done automatically for you.

Handling Drop-Downs

The v-model directive is also used for dropdowns. In the template, you are to loop through a collection of values, as these values are automatically populated in your form.

Here is a drop-down that loops through a list; the list will be defined in the data model.

<div class="row"> <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 from-group"> <label for="expertise">Expertise</label> <select id="expertise" class="form-control" v-model="selectedExpertise"> <option v-for="expertise in expertises">{{ expertise }}</option> </select> </div> </div>

The data model should look like this.

data () { return { userData: { email: '', password: '', age: 40 }, message: 'This is a placeholder text', occupation: [], gender: 'Female, selectedExpertise: 'Professional', expertises: ['Newbie', 'Beginner', 'Professional', 'Expert'] } }

The binding is done on the select tag element, and not on the individual options. A default option is set in the data model when a user selects another option, and the selectedExpertise gets updated.

Form Submission

Here, you'll add a submit button. You'll need to prevent the submit button from submitting the form to the server, which is its default behaviour. You'll substitute that with displaying the form on the page. 

Thus there will need to be a method that changes the value of the display section to true. When true, the display section is expected to show the values of the form. Start by adding the submit button.

<div class="row"> <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3"> <button class="btn btn-primary" @click.prevent="submitted">Submit!</button> </div> </div>

Here, you're listening for the click event, and when the button gets clicked, you want to call a method. This method needs to be added to the script section of your code.

<script> export default { data () { return { userData: { email: '', password: '', age: 40 }, message: 'This is a placeholder text', occupation: [], gender: 'Female, selectedExpertise: 'Professional', expertises: ['Newbie', 'Beginner', 'Professional', 'Expert'] } }, methods: { submitted() { this.isSubmitted = true; } } } </script>

With that done, you can add the display section, after the closing tag of the form.

<hr> <div class="row" v-if="isSubmitted"> <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3"> <div class="panel panel-default"> <div class="panel-heading"> <h4>Your Data</h4> </div> <div class="panel-body"> <p>Mail: {{ userData.email }} </p> <p>Password: {{ userData.password }}</p> <p>Age: {{ userData.age }}</p> <p style="white-space: pre">Message: {{ message }}</p> <p><strong>Interest</strong></p> <ul> <li v-for="item in interest">{{ item }}</li> </ul> <p>Gender: {{ gender }}</p> <p>Priority: {{ selectedExpertise }}</p> </div> </div> </div> </div>

With that, when the submit button gets clicked, the values entered in the form will be displayed.

Conclusion

At this point, you can work effectively with forms when building applications using Vue.js. If you’re looking for additional resources to study or to use in your work, check out what we have available in the Envato Market.

You learned how to work with all possible parts of a form you might encounter in your journey as a developer. You've tried your hand at inputs, select options, radios, checkboxes, and textarea. 

Thanks for reading!

Categories: Web Design

How to Send Emails in Laravel

Fri, 12/29/2017 - 04:00

In this article, we're going to explore the Mail API in the Laravel web framework. Laravel takes advantage of the popular SwiftMailer library, which is easy to use and comes with a variety of email drivers to choose from. In the latter stages of the article, we'll go through an in-depth demonstration of the concepts discussed in the first half of the article.

Setting Up the Prerequisites

Laravel implements a wrapper on top of the SwiftMailer library that makes email management very easy to configure and use at the same time. You can find the default mail settings at config/mail.php.

<?php return [ /* |-------------------------------------------------------------------------- | Mail Driver |-------------------------------------------------------------------------- | | Laravel supports both SMTP and PHP's "mail" function as drivers for the | sending of e-mail. You may specify which one you're using throughout | your application here. By default, Laravel is setup for SMTP mail. | | Supported: "smtp", "sendmail", "mailgun", "mandrill", "ses", | "sparkpost", "log", "array" | */ 'driver' => env('MAIL_DRIVER', 'sendmail'), /* |-------------------------------------------------------------------------- | SMTP Host Address |-------------------------------------------------------------------------- | | Here you may provide the host address of the SMTP server used by your | applications. A default option is provided that is compatible with | the Mailgun mail service which will provide reliable deliveries. | */ 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), /* |-------------------------------------------------------------------------- | SMTP Host Port |-------------------------------------------------------------------------- | | This is the SMTP port used by your application to deliver e-mails to | users of the application. Like the host we have set this value to | stay compatible with the Mailgun e-mail application by default. | */ 'port' => env('MAIL_PORT', 587), /* |-------------------------------------------------------------------------- | Global "From" Address |-------------------------------------------------------------------------- | | You may wish for all e-mails sent by your application to be sent from | the same address. Here, you may specify a name and address that is | used globally for all e-mails that are sent by your application. | */ 'from' => [ 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), 'name' => env('MAIL_FROM_NAME', 'Example'), ], /* |-------------------------------------------------------------------------- | E-Mail Encryption Protocol |-------------------------------------------------------------------------- | | Here you may specify the encryption protocol that should be used when | the application send e-mail messages. A sensible default using the | transport layer security protocol should provide great security. | */ 'encryption' => env('MAIL_ENCRYPTION', 'tls'), /* |-------------------------------------------------------------------------- | SMTP Server Username |-------------------------------------------------------------------------- | | If your SMTP server requires a username for authentication, you should | set it here. This will get used to authenticate with your server on | connection. You may also set the "password" value below this one. | */ 'username' => env('MAIL_USERNAME'), 'password' => env('MAIL_PASSWORD'), /* |-------------------------------------------------------------------------- | Sendmail System Path |-------------------------------------------------------------------------- | | When using the "sendmail" driver to send e-mails, we will need to know | the path to where Sendmail lives on this server. A default path has | been provided here, which will work well on most of your systems. | */ 'sendmail' => '/usr/sbin/sendmail -bs', /* |-------------------------------------------------------------------------- | Markdown Mail Settings |-------------------------------------------------------------------------- | | If you are using Markdown based email rendering, you may configure your | theme and component paths here, allowing you to customize the design | of the emails. Or, you may simply stick with the Laravel defaults! | */ 'markdown' => [ 'theme' => 'default', 'paths' => [ resource_path('views/vendor/mail'), ], ], ];

When it comes to sending mails, Laravel supports different drivers to choose from. As you can see, the default MAIL_DRIVER is set to smtp.

If you are going to use the smtp driver to send mails then you're also required to set other related settings like MAIL_HOST, MAIL_PORT, MAIL_ENCRYPTION, MAIL_USERNAME, and MAIL_PASSWORD.

On the other hand, if you are going to use the sendmail driver, then you want to make sure that the sendmail system path is set to the correct value in the config/mail.php file.

You can also set the from address that will be used while sending mails under the from key. And finally, if you want to use Markdown-based email rendering, you can set those settings under the markdown key.

The cherry on the top is that you could also use third-party email service providers like Mailgun, Mandrill, SES, and SparkPost. If you are using one of those services, you need to make sure that you set the corresponding settings in the config/services.php file.

So that was a basic introduction to the mail API related settings in Laravel. From the next section onwards, we'll go through a custom example that shows you how to send emails.

Create the Mailable Class

In this section, we'll create the mailable class, which will be used to send emails. The mailable class is responsible for sending emails using a mailer that's configured in the config/mail.php file. In fact, Laravel already provides an artisan command that allows us to create a base template.

php artisan make:mail DemoEmail

That should create a blank email template at app/Mail/DemoEmail.php, as shown in the following snippet.

<?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Queue\ShouldQueue; class DemoEmail extends Mailable { use Queueable, SerializesModels; /** * Create a new message instance. * * @return void */ public function __construct() { // } /** * Build the message. * * @return $this */ public function build() { return $this->view('view.name'); } }

Let's replace the contents of that file with the following.

<?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Queue\ShouldQueue; class DemoEmail extends Mailable { use Queueable, SerializesModels; /** * The demo object instance. * * @var Demo */ public $demo; /** * Create a new message instance. * * @return void */ public function __construct($demo) { $this->demo = $demo; } /** * Build the message. * * @return $this */ public function build() { return $this->from('sender@example.com') ->view('mails.demo') ->text('mails.demo_plain') ->with( [ 'testVarOne' => '1', 'testVarTwo' => '2', ]) ->attach(public_path('/images').'/demo.jpg', [ 'as' => 'demo.jpg', 'mime' => 'image/jpeg', ]); } }

There are two important methods the mailable class generally implements—__construct and build. The __construct method is used to initialize objects that you're supposed to use in the email template. On the other hand, the build method is used to initialize more email-specific values like from, view template, attachments and similar.

In our case, we've passed the $demo object as a constructor argument, and it's assigned to the demo public property.

In the build method, we've initialized an email-specific configuration.

  • The from is used to set an email address that'll be used as a from address.
  • Using the view method, you can set the email template that will be used while sending an email using this mailable. In our case, we've set it to mails.demo, and it means that you need to create a view template file at resources/views/mails/demo.blade.php.
  • Next, the text method is used to set up the plain text version of an email template.
  • As we've just discussed, the __construct method is used to set up objects that'll be used in the email template, you can also use the with method that allows you to set the view data of a message.
  • Next, we've used the attach method to attach an image with a message.

Of course, we need to create email templates that we're supposed to use while sending emails. Go ahead and create a file resources/views/mails/demo.blade.php as shown in the following snippet.

Hello <i>{{ $demo->receiver }}</i>, <p>This is a demo email for testing purposes! Also, it's the HTML version.</p> <p><u>Demo object values:</u></p> <div> <p><b>Demo One:</b>&nbsp;{{ $demo->demo_one }}</p> <p><b>Demo Two:</b>&nbsp;{{ $demo->demo_two }}</p> </div> <p><u>Values passed by With method:</u></p> <div> <p><b>testVarOne:</b>&nbsp;{{ $testVarOne }}</p> <p><b>testVarTwo:</b>&nbsp;{{ $testVarTwo }}</p> </div> Thank You, <br/> <i>{{ $demo->sender }}</i>

Also, let's create the plain text version of that file at resources/views/mails/demo_plain.blade.php.

Hello {{ $demo->receiver }}, This is a demo email for testing purposes! Also, it's the HTML version. Demo object values: Demo One: {{ $demo->demo_one }} Demo Two: {{ $demo->demo_two }} Values passed by With method: testVarOne: {{ $testVarOne }} testVarOne: {{ $testVarOne }} Thank You, {{ $demo->sender }}

So that was the mailable class at your disposal, and we've not done yet as we need to use the Mail facade to actually send mails. In the very next section, we'll explore how you can use the Mail Facade to send emails using the DemoEmail Mailable class that was just created in this section.

Wrapping Up

In this section, we'll create an example to demonstrate how you can use the Mailable class that was created in the last section.

Let's create a controller file at app/Http/Controllers/MailController.php with the following contents.

<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Mail\DemoEmail; use Illuminate\Support\Facades\Mail; class MailController extends Controller { public function send() { $objDemo = new \stdClass(); $objDemo->demo_one = 'Demo One Value'; $objDemo->demo_two = 'Demo Two Value'; $objDemo->sender = 'SenderUserName'; $objDemo->receiver = 'ReceiverUserName'; Mail::to("receiver@example.com")->send(new DemoEmail($objDemo)); } }

It's important to note that we've included the Illuminate\Support\Facades\Mail Facade that will be used to send an email. In the send method, the following statement is responsible for sending an email by initialising the App\Mail\DemoEmail Mailable in the first place.

Mail::to("receiver@example.com")->send(new DemoEmail($objDemo));

The to method of the Illuminate\Support\Facades\Mail Facade returns an instance of the \Illuminate\Mail\PendingMail class, which already contains an appropriate mailer configured in the config/mail.php file.

And finally, we use the send method of the \Illuminate\Mail\PendingMail class that sends an actual email.

To test it, let's add an associated route in the routes/web.php file.

// Email related routes Route::get('mail/send', 'MailController@send');

And with that in place, you can run the http://your-laravel-site.com/mail/send URL to see if it works as expected.

On the other hand, if you want to test your email templates quickly, without sending actual emails, there's a provision in Laravel that allows you to log all outgoing emails.

To achieve that, you need to set the value of MAIL_DRIVER to log in the config/mail.php file. Next, you could run the aforementioned URL and inspect the log file to check if the email template was logged there.

If everything goes fine, you should see an email being logged to the storage/logs/laravel.log file.

That's pretty much it as far as the mail feature is concerned in Laravel, and that concludes this article as well.

Conclusion

Today, we went through the mail API that comes built into Laravel, and it also supports a variety of drivers as well.

Starting with basic concepts, we implemented the mailable class that is an essential element in the mail API in Laravel as we moved on. At the end, we also tested the mailable class by creating a custom controller to see if it actually works.

If you're just getting started with Laravel or looking to expand your knowledge, site, or application with extensions, we have a variety of things you can study in Envato Market.

I would love to know your feedback in the form of queries and comments using the feed below!

Categories: Web Design

Components in Vue.js

Tue, 12/26/2017 - 04:00
Introduction

Vue.js components are important to understand as you work with Vue.js. In this tutorial we are going to dig into Vue.js components, understanding the basics and applying them to an application. Let's get started.

What Are Components?

Components enable us to break the complexity of an application into tiny chunks. For example, a typical web application will have sections like header, sidebar, content, and footer.

Vue.js allows us to break each of these sections into separate modular code called components. These components can be extended, and then attached to the application you are working on. Components are a great way of reusing your code throughout your application.

Let's say you have a blog application, and you would like to display a list of blog posts. Using a Vue component, you can do:

<blog-post></blog-post>

Vue handles the rest.

Create a simple HTML page that mounts a Vue instance to your DOM element. You will use this to learn about components. Here is what the sample HTML page should look like:

<!DOCTYPE html> <html> <head> <title>VueJs Components</title> </head> <body> <!-- Div where Vue instance will be mounted --> <div id="app"></div> <!-- Vue.js is included in your page via CDN --> <script src="https://unpkg.com/vue"></script> <script> // A new Vue instance is created and mounted to your div element new Vue({ el: '#app', data: { domain: 'Tutsplus' }, template: '<p>Welcome to {{ domain }}</p> }); </script> </body> </html>

In the above, you created a simple Vue instance, with no component factor in the code. Now if you want the welcome message to appear twice, how do you do it? Try getting that to work.

Your guess might be to have the div where the Vue instance is mounted appear twice. That will not work. Try changing it from id to class so you have this:

<!DOCTYPE html> <html> <head> <title>VueJs Components</title> </head> <body> <!-- Div where Vue instance will be mounted --> <div class="app"></div> <div class="app"></div> <!-- Vue.js is included in your page via CDN --> <script src="https://unpkg.com/vue"></script> <script> // A new Vue instance is created and mounted to your div element new Vue({ el: '.app', data: { domain: 'Tutsplus' }, template: '<p>Welcome to {{ domain }}</p> }); </script> </body> </html>

It still will not work!

The only way to get around this is to create a component. How do you create a component?

Components are created using the Vue.component() constructor. This constructor takes two parameters: the name of your component (which can also be called the tag name), and an object containing options for your component.

Let's create a component using what you have above.

Vue.component('welcome-message', { data: function() { return { domain: 'Tutsplus' } }, template: '<p>Welcome to {{ domain }}</p>' })

In the above, the component name is called welcome-message. Your component can have whatever name you choose. Yet it is important that the name does not interfere with any HTML tags, as you will not want to override it.

The options object passed to the constructor contains the data and template. When creating components, your data should be a function, as you can see above. The data being held should then be returned as an object.

In situations where there are no data to pass, you can pass only the template like so:

Vue.component('welcome-message', { template: '<p>Welcome to Tutsplus</p>' })

With that done, you can use your component in your application by calling it like a regular HTML element using the name you passed to the constructor. It is called like this: <welcome-message></welcome-message>.

To output the template more than once, you call the component as many times as you want—as I did below.

<!DOCTYPE html> <html> <head> <title>VueJs Components</title> </head> <body> <!-- Div where Vue instance will be mounted --> <div id="app"> <welcome-message></welcome-message> <welcome-message></welcome-message> <welcome-message></welcome-message> <welcome-message></welcome-message> </div> <!-- Vue.js is included in your page via CDN --> <script src="https://unpkg.com/vue"></script> <script> Vue.component('welcome-message', { data: function() { return { domain: 'Tutsplus' } }, template: '<p>Welcome to {{ domain }}</p>' }) // A new Vue instance is created and mounted to your div element new Vue({ el: '#app' }); </script> </body> </html>

From the above, this will display the welcome message four times.

Store Data in Components

Above I mentioned that data has to be a function, and the information it holds has to be returned as an object. Why is it like that?

When returned data is not an object, the components that make use of that data share the same source: shared data. Thus a change in data for one component affects the other component. This is not the same when the data is returned as an object.

It is important to see how this works practically. First, let's see a situation where data is returned as an object.

<!DOCTYPE html> <html> <head> <title>VueJs Components</title> </head> <body> <!-- Div where Vue instance will be mounted --> <div id="app"> <welcome-message></welcome-message> <welcome-message></welcome-message> </div> <!-- Vue.js is included in your page via CDN --> <script src="https://unpkg.com/vue"></script> <script> var data = { name: 'Henry' } Vue.component('welcome-message', { data: function() { return data }, template: '<p>Hello {{ name }}, welcome to TutsPlus (<button @click="changeName">Change Name</button>)</p>', methods :{ changeName: function() { this.name = 'Mark' } } }) // A new Vue instance is created and mounted to your div element new Vue({ el: '#app' }); </script> </body> </html>

Can you guess what is happening above?

There are two components, and both components share the same data source as the data is not returned as an object. How do you prove I am right? When you view the above page from your browser, you will see that a change in one component results in a change in the data of the other component. How is it supposed to be?

Like this:

<!DOCTYPE html> <html> <head> <title>VueJs Components</title> </head> <body> <!-- Div where Vue instance will be mounted --> <div id="app"> <welcome-message></welcome-message> <welcome-message></welcome-message> </div> <!-- Vue.js is included in your page via CDN --> <script src="https://unpkg.com/vue"></script> <script> Vue.component('welcome-message', { data: function() { return { name: 'Henry' } }, template: '<p>Hello {{ name }}, welcome to TutsPlus (<button @click="changeName">Change Name</button>)</p>', methods :{ changeName: function() { this.name = 'Mark' } } }) // A new Vue instance is created and mounted to your div element new Vue({ el: '#app' }); </script> </body> </html>

Here the data is returned as an object, and a change in one component does not affect the other. The function is executed for the individual component. When building your applications, it is important you do not forget this.

Creating and Using Components

Using the lessons learned thus far, let us implement this in a new Vue.js project started from scratch using vue-cli. If you do not have vue-cli installed on your machine, you can do that by running:

npm install -g vue-cli

Start your new Vue.js project:

vue init webpack vue-component-app

Navigate to your application, install the dependencies, and run your dev server using the commands below.

cd vue-component-app npm install npm run dev

First, you'll rename the HelloWorld component that was created when you initialized your application to Hello.vue. You'll then register this component as a global component to be used in your application.

So your Hello component should look like this.

#src/components/Hello.vue <template> <div class="hello"> <p>Welcome to TutsPlus {{ name }}</p> <hr> <button @click="changeName">Change Display Name</button> </div> </template> <script> export default { name: 'Hello', data () { return { name: 'Henry' } }, methods: { changeName () { this.name = 'Mark' } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>

Nothing serious is happening here. You have your welcome text displaying the welcome message and a name which is passed as data. When the button underneath the welcome message gets clicked, the changeName method is called. This changes the name from Henry to Mark.

To use this component globally it has to be registered. Can you guess where that will be done? If you said main.js, you are absolutely correct.

To register a component, you import it and then use the Vue.component() constructor to set it up. Try that on your own.

I bet you got that to work. Here is how things should look in your main.js file.

#src/main.js // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import Home from './components/Hello' Vue.config.productionTip = false Vue.component('display-name', Home) /* eslint-disable no-new */ new Vue({ el: '#app', template: '<App/>', components: { App } })

Nothing new here except the line that imports your Hello component. The component is then registered using the constructor. Finally, for this part, the component needs to be displayed using the component name you entered. In this case, the component is display-name. This will be done in your App.vue file.

Open up src/App.vue and make it look like this.

#src/App.vue <template> <div id="app"> <display-name/> </div> </template> <script> export default { } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>

With your server on, point your browser to http://localhost:8080. Click on the button and the name should change.

Let's see how to use a component locally.

Create a file called Detail.vue in your components directory. This component will not do anything special—it will be used in the Hello component.

Make your Detail.vue file look like this.

#src/components/Detail.vue <template> <div class="hello"> <p>This component is imported locally.</p> </div> </template> <script> export default { name: 'Detail' } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>

To use it in the Hello component, you start by importing it, as you did with the Hello component. Next, you register it, but this time you will not make use of the Vue.component() constructor.

You register it using the components object inside your exports. The name of the component which will be used as the element tag has to be passed as a value to the object. With that done, you can now use the element tag to output the component.

To understand all that, here is how the Hello component should look.

#src/components/Hello.vue <template> <div class="hello"> <p>Welcome to TutsPlus {{ name }}</p> <hr> <button @click="changeName">Change Display Name</button> <!-- Detail component is outputted using the name it was registered with --> <Detail/> </div> </template> <script> // Importation of Detail component is done import Detail from './Detail' export default { name: 'HelloWorld', data () { return { name: 'Henry' } }, methods: { changeName () { this.name = 'Mark' } }, /** * Detail component gets registered locally. * This component can only be used inside the Hello component * The value passed is the name of the component */ components: { Detail } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>

Refresh your page to see the new page.

Scoping Component Styles

Vue.js allows you to give global and local styling for your components. What do I mean? There might be scenarios where you want certain elements in a component to be styled differently from their counterparts in another component. Vue.js has got you covered on that.

A good example is available in the little app you just built. The styles in your App.vue are global; how is that possible? Open your App.vue, and the style section looks like this.

<style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>

This is different from that of Detail.vue, which looks like this.

<style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>

Adding scoped to the style tag makes all the difference. Try editing one of the component styles by removing scoped, and you will see how that works out.

Conclusion

That was a long one, and I trust you enjoyed it.

Now you know how to work effectively with components. You understand how to construct a component in an existing application. When working with vue-cli, you can also create and use components—locally and globally. When you want to use a particular style for a component, you saw how to do that using scoped.

You can now go on to build a complex Vue.js application that uses components. Understand that Vue.js allows you to reuse code—your headers, footer, login panel, and search bar can be used as components.

Categories: Web Design

10 Best HTML5 Sliders for Images and Text

Fri, 12/22/2017 - 04:00

HTML5 enables users to have a better and more consistent web experience across several devices. 

Considering that smart devices of varying screen sizes and resolutions are the number one way that most people now access the web, if you have image-rich content or want to present key text in an interesting and exciting way on your website, then you just can't go wrong by using an HTML5 slider. 

Because there are such a large number of sliders out there to choose from, I've pulled together, just for you, a list of the 10 best HTML5 sliders for images and text available at CodeCanyon.

1. Ultimate 3D Carousel

If you’ve ever seen or used an actual slide carousel, you’ll appreciate the design and aesthetics of the Ultimate 3D Carousel. This carousel slider allows you to display multimedia content with a unique 3D layout that mimics the carousels of film photography days. 

There are a number of effects you can apply to your carousel style if you choose, and if you prefer a more traditional slide effect, you can also opt for that instead of the carousel style.

The carousel supports images, MP4 videos, MP3 audio, Google Maps, and more. It runs on all major browsers and uses a responsive layout with auto-scale function so that it works well on all mobile devices.

2. HTML5 Gallery Slideshow

The HTML5 Gallery Slideshow is an excellent choice for showing off your images and text in a slider format. The slideshow’s main selling point is that it is super easy to use. Just add it wherever you want it to appear on your website, and it will adapt its size to the parent container, i.e. the div or other HTML tag. 

Another great feature is that you can have as many galleries on the same page as you want, each with its unique set of images and settings. 

The plugin is also easily customisable. You can change the colour theme and modify the buttons and other aspects, in order to integrate it seamlessly into your site. The slideshow has been coded and optimised to run seamlessly on mobile devices as well.

3. CCSlider Plugin

The CCSlider Plugin offers users a number of options of slider styles, each of which can be customised in numerous ways. You have the choice of 14 3D transitions and 16 2D transitions in total, all of which can be programmed to play automatically, manually, or both.

Captions can be added to each slide, and they can have animated transitions or none at all. The sliders are fully responsive so they work well on mobile devices and support touch gestures.

4. HTML5 Fullscreen Gallery

The HTML5 Fullscreen Gallery was created specifically for showcasing great photographs. The gallery is super easy to incorporate into your existing website and will maintain the correct aspect ratio of all photographs when resizing the browser window. 

You can add titles and descriptions if you wish, and all colours can be altered via the CSS stylesheet. 

For those who want music with their sliders, this gallery comes with piano music played via the HTML5 audio tag, which falls back to Flash music player for incompatible browsers.

5. CSS3 Cube Slider

If you’re looking for a slider with a bit of a difference, check out the CSS3 Cube Slider. This slider shows off your images in a gorgeous slider form like the other sliders here, but it does so by transforming your photos into a choice of six cool 3D cubes as they transition.

The plugin works best in Chrome, Firefox, and Safari browsers, but if the browser doesn’t support CSS3 then the slider falls back to the standard vertical or horizontal slide transition. The plugin is responsive and will adapt to any screen size for the user’s devices.

6. HTML5 Responsive Slider Gallery

HTML5 Responsive Slider Gallery is a wonderful tool that image-rich site owners will want to get their hands on to show off their images to their best advantage.

You just have to check out the live preview for the HTML5 Responsive Slider Gallery to understand why it’s a bestseller at CodeCanyon. 

The slider gallery will adapt both height and width to any space that you added it to based on the parent container. It uses a graphics processing unit for peak performance on both your desktop and mobile devices, comes in three different styles, supports multiple galleries on the same page, and is highly customisable.

7. HTML5 Canvas Carousel

The HTML5 Canvas Carousel gives you another great option to display your images on your website. This 3D photo gallery offers six different options for presenting your images. 

Features include touch-screen navigation support for mobile, support for PNG, JPEG and GIF image files, ability to set the carousel position, and the possibility of featuring multiple carousels on the same page of your website. 

The carousel is highly customisable, and all options can be modified inside the XML file. It is optimized for both Android and iOS mobile devices, and the download file comes with a comprehensive help file explaining all configuration tags and installation.

8. Ultimate Media Gallery

The Ultimate Media Gallery is unique among the sliders in this list, because it can display not just images but video and audio files from a number of external content sources including YouTube, Vimeo, Google Drive media, Podcast, and SoundCloud.  

This highly customisable gallery is fully responsive and mobile friendly. It takes full advantage of Font Awesome Library icons, and all demo examples are included in the download package for quick and easy setup.

9. HTML5 Canvas Cover Flow

The HTML5 Canvas Cover Flow is a 3D photo gallery that takes its inspiration from the Mac Finder viewer of the same name. The slider has tons of features and allows you to present your images in any way you want: horizontal, vertical, oblique, etc. Alternatively, you can make use of the predefined movements and styles if preferred.

In addition, almost every aspect of the slider including colours and graphic elements can be customised to fit your site, and all the options can be easily modified from the configuration XML file, making maintaining the carousel much easier.

Optimised for mobile devices, it not only runs on them, but acts like a native app where you can touch, drag, and rotate the controls.

10. AZEXO Slider

A modernist take on the slider, AZEXO Slider is ideal for those who have a minimalist aesthetic and are looking for a clean yet elegant way to display their images. 

Text can be added over every image, making the slider ideal for presentations that include quotes or important text. 

The transition sequence can be customised, and the slider is easy to incorporate into your website with the addition of the “azexo-slider” class to DIVs which contain images.

Conclusion

These 10 best HTML5 sliders for images and text are by no means the only ones available at Envato Market. So if you haven’t found anything here that meets your needs, we have plenty of other great options on offer.

And if you want to improve your HTML5 skills, check out our ever so useful free HTML5 tutorials.

Categories: Web Design

Site Authentication in Node.js: User Signup

Thu, 12/21/2017 - 04:00
Introduction

Just as authentication is important in APIs, it is also an important feature in certain web applications—those with pages and secrets that should only be accessible to registered and authenticated users.

In this tutorial, you will build a simple web application while learning how to create user registration.

Application Setup

Create a new directory where you will be working from. For the sake of this tutorial, I called mine site-auth. Initialize npm in the new directory you just created. Here is how to initialize npm.

npm init -y

The -y flag tells npm to use the default options.

Edit the dependencies part of your package.json file to look like what I have in mine.

#package.json { "name": "site-auth", "version": "1.0.0", "description": "", "main": "app.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "izuchukwu1", "license": "ISC", "dependencies": { "bcryptjs": "^2.4.3", "body-parser": "^1.17.1", "connect-flash": "^0.1.1", "cookie-parser": "^1.4.3", "express": "^4.15.2", "express-handlebars": "^3.0.0", "express-messages": "^1.0.1", "express-session": "^1.15.2", "joi": "^13.0.1", "mongoose": "^4.11.12", "morgan": "^1.8.1", "passport": "^0.4.0", "passport-local": "^1.0.0" } }

With that done, run the command to install the dependencies.

npm install

Create a file in your working directory called app.js.

Start by requiring the dependencies you installed and the necessary files.

#app.js const express = require('express'); const morgan = require('morgan') const path = require('path'); const cookieParser = require('cookie-parser'); const bodyParser = require('body-parser'); const expressHandlebars = require('express-handlebars'); const flash = require('connect-flash'); const session = require('express-session'); const mongoose = require('mongoose') const passport = require('passport') require('./config/passport')

These dependencies were installed when you ran npm install. To use them in your application, you have to require them and save them in their respective variables.

For this tutorial, you will be using MongoDB as your database. You will need to store user information in the database. To work with MongoDB, you will make use of Mongoose—a MongoDB modelling tool for Node.js. Setting up Mongoose is easy, like this.

#app.js mongoose.Promise = global.Promise mongoose.connect('mongodb://localhost:27017/site-auth')

At this point, let's set up our middleware.

// 1 const app = express() app.use(morgan('dev')) // 2 app.set('views', path.join(__dirname, 'views')) app.engine('handlebars', expressHandlebars({ defaultLayout: 'layout' })) app.set('view engine', 'handlebars') // 3 app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: false })) app.use(cookieParser()) app.use(express.static(path.join(__dirname, 'public'))) app.use(session({ cookie: { maxAge: 60000 }, secret: 'codeworkrsecret', saveUninitialized: false, resave: false })); app.use(passport.initialize()) app.use(passport.session()) // 4 app.use(flash()) app.use((req, res, next) => { res.locals.success_mesages = req.flash('success') res.locals.error_messages = req.flash('error') next() }) // 5 app.use('/', require('./routes/index')) app.use('/users', require('./routes/users')) // 6 // catch 404 and forward to error handler app.use((req, res, next) => { res.render('notFound') }); // 7 app.listen(5000, () => console.log('Server started listening on port 5000!'))
  1. Express is initialized and assigned to app.
  2. Middleware to handle views is set up. For the views, you'll be making use of handlebars.
  3. You set up middleware for bodyparser, cookie, session, and passport. Passport will be used when users want to log in.
  4. At some points, you will be displaying flash messages. Thus you need to set up middleware for that, and also create the type of flash messages you want.
  5. Routes middleware—this will handle any request made to a URL path. The URL paths specified here are for the index and users path.
  6. Middleware to handle 404 errors. This middleware kicks in when a request does not map to any of the middleware created above it.
  7. The server is set to listen at port 5000.
Views Setup

Create a new directory called views. Inside the views directory, create two other directories called layouts and partials. You want to achieve a tree structure like this in your views, so create the necessary files in their respective directories.

├── dashboard.handlebars ├── index.handlebars ├── layouts │   └── layout.handlebars ├── login.handlebars ├── notFound.handlebars ├── partials │   └── navbar.handlebars └── register.handlebars

With that done, time to drop the code.

#dashboard.handlebars <!-- Jumbotron --> <div class="jumbotron"> <h1>User DashBoard</h1> </div>

This is a dashboard that should be visible to only registered users. For this tutorial, it will be your secret page.

Now the index page for the application should look like this.

#index.handlebars <!-- Jumbotron --> <div class="jumbotron"> <h1>Site Authentication!</h1> <p class="lead">Welcome aboard.</p> </div>

The application needs a layout that will be used, and here is that layout you will be using.

#layout/layout.handlebars <!DOCTYPE html> <html> <head> <title>Site Authentication</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <link rel="stylesheet" href="/css/style.css"> </head> <body> {{#if success_messages }} <div class="alert alert-success">{{success_messages}}</div> {{/if}} {{#if error_messages }} <div class="alert alert-danger">{{error_messages}}</div> {{/if}} <div class="container"> {{> navbar}} {{{body}}} </div> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> </body> </html>

You'll need a login page for registered users.

#views/login.handlebars <form class="form-signin" action="/users/login" method="POST"> <h2 class="form-signin-heading">Please sign in</h2> <label for="inputEmail" class="sr-only">Email address</label> <input type="email" id="inputEmail" name="email" class="form-control" placeholder="Email address" required autofocus> <label for="inputPassword" class="sr-only">Password</label> <input type="password" id="inputPassword" name="password" class="form-control" placeholder="Password" required> <br/> <button class="btn btn-lg btn-default btn-block" type="submit">Sign in</button> </form>

The notFound.handlebars file will be used as your error page.

#views/notFound.handlebars <!-- Jumbotron --> <div class="jumbotron"> <h1>Error</h1> </div>

Your registration page is supposed to look like this.

<form class="form-signin" action="/users/register" method="POST"> <h2 class="form-signin-heading">Please sign up</h2> <label for="inputEmail" class="sr-only">Email address</label> <input type="email" id="inputEmail" name="email" class="form-control" placeholder="Email address" required autofocus> <label for="inputUsername" class="sr-only">Username</label> <input type="text" id="inputUsername" name="username" class="form-control" placeholder="Username" required> <label for="inputPassword" class="sr-only">Password</label> <input type="password" id="inputPassword" name="password" class="form-control" placeholder="Password" required> <label for="inputConfirmPassword" class="sr-only">Confirm Password</label> <input type="password" id="inputConfirmPassword" name="confirmationPassword" class="form-control" placeholder="Confirm Password" required> <br/> <button class="btn btn-lg btn-default btn-block" type="submit">Sign up</button> </form>

Finally for your views, here's your navigation bar.

#partials/navbar.handlebars <div class="masthead"> <h3 class="text-muted">Site Authentication</h3> <nav> <ul class="nav nav-justified"> <li class="active"><a href="/">Home</a></li> {{#if isAuthenticated}} <li><a href="/users/dashboard">Dashboard</a></li> <li><a href="/users/logout">Logout</a></li> {{else}} <li><a href="/users/register">Sign Up</a></li> <li><a href="/users/login">Sign In</a></li> {{/if}} </ul> </nav> </div>

With that done, you are good to go into some deep parts.

Data Validation

You'll need a User model. From the views code above, you can deduce that the properties needed for the User model are email, username, and password. Create a directory called models, and a file in it called user.js.

#models/user.js // 1 const mongoose = require('mongoose') const Schema = mongoose.Schema const bcrypt = require('bcryptjs') // 2 const userSchema = new Schema({ email: String, username: String, password: String }, { // 3 timestamps: { createdAt: 'createdAt', updatedAt: 'updatedAt' } }) // 4 const User = mongoose.model('user', userSchema) module.exports = User
  1. Imports dependencies and saves them in variables.
  2. A new Schema is created. For each user, you want to save the email, username, and password to the database. The Schema shows how the model is to be constructed for each document. Here you want the email, username, and password to be of the String type.
  3. For each user saved to the database, you also want to create timestamps. You utilize Mongoose to obtain the createdAt and updatedAt, and this is then saved to the database.
  4. The model is defined and assigned to a variable called User, which is then exported as a module so it can be used in other parts of the application.
Salting and Hashing of the Password

You do not want to store users' passwords as plain text. Here's what you want to do when a user enters a plain text password while registering. The plain text password should be hashed using a salt that will be generated by your application (using bcryptjs). This hashed password is then stored in the database. 

Sounds great, right? Let's implement that in the user.js file.

#models/user.js module.exports.hashPassword = async (password) => { try { const salt = await bcrypt.genSalt(10) return await bcrypt.hash(password, salt) } catch(error) { throw new Error('Hashing failed', error) } }

You just created a method that will be called in events of user registration. The method will receive the plain text password the user entered. As I mentioned earlier, the plain text password will be hashed using a generated salt. The hashed password will be returned as the password for the user.

Index and Users Routes 

Create a new directory called routes. In this new directory, create two new files: index.js and users.js.

The index.js file will be very simple. It will map to the index of your application. Remember you set up middleware for your routes in your app.js file when you did this.

app.use('/', require('./routes/index')) app.use('/users', require('./routes/users'))

So your index routes, which simply render the index page, should look like this.

#routes/index.js const express = require('express') const router = express.Router() router.get('/', (req, res) => { res.render('index') }) module.exports = router

Now to the users route. For now, this route file will be doing four things.

  1. Require dependencies. You will need to require the dependencies you installed using NPM.
  2. Validate user inputs. You want to make sure that the user does not submit an empty form. All inputs are required, and all must be of the type String. The email has a special validation called .email() which ensures that what is entered matches the email format, while the password is validated using a regular expression. For the confirmation password, you want it to be the same as the password entered. These validations are done using Joi.
  3. Set up your router. The get request renders the registration page, while the POST request kicks in when the user hits the button to submit the form.
  4. The router gets exported as a module.

Here is what the code looks like.

#routes/users.js const express = require('express'); const router = express.Router() const Joi = require('joi') const passport = require('passport') const User = require('../models/user') //validation schema const userSchema = Joi.object().keys({ email: Joi.string().email().required(), username: Joi.string().required(), password: Joi.string().regex(/^[a-zA-Z0-9]{6,30}$/).required(), confirmationPassword: Joi.any().valid(Joi.ref('password')).required() }) router.route('/register') .get((req, res) => { res.render('register') }) .post(async (req, res, next) => { try { const result = Joi.validate(req.body, userSchema) if (result.error) { req.flash('error', 'Data entered is not valid. Please try again.') res.redirect('/users/register') return } const user = await User.findOne({ 'email': result.value.email }) if (user) { req.flash('error', 'Email is already in use.') res.redirect('/users/register') return } const hash = await User.hashPassword(result.value.password) delete result.value.confirmationPassword result.value.password = hash const newUser = await new User(result.value) await newUser.save() req.flash('success', 'Registration successfully, go ahead and login.') res.redirect('/users/login') } catch(error) { next(error) } }) module.exports = router

Let's look deeper into what is happening in that POST request.

The values entered in the registration form are accessible via req.body, and the values look like this.

value: { email: 'chineduizuchkwu1@gmail.com', username: 'izu', password: 'chinedu', confirmationPassword: 'chinedu' },

This is validated using the userSchema you created above, and the values entered by the user are assigned to a variable called result.

If an error is encountered because of the validation, an error message is displayed to the user and a redirection to the registration page takes place.

Otherwise, we try to find if a user with the same email address exists, as you do not want to have two or more users with same email address. If a user is found, the user is told that the email address is already in use.

In a scenario where no registered user has that email address, the next step is to hash the password. This is where you call the hashPassword method you created in your user.js file. The new hashed password is assigned to a variable called hash.

There is no need to store the confirmationPassword in the database. Thus this is deleted. The password available from result is still the plain password. Since you do not want to store the plain password in your database, it is important to reassign the password value to the hash that was created. This is done with a line of code.

result.value.password = hash

The new user instance gets saved to the database. A flash message stating that the registration was successful is displayed, and the user is redirected to the login page.

Start up your server from your terminal by running:

node app.js

Point your browser to http://localhost:5000 and you should see your new app.

Conclusion

Now you know how to implement the registration feature in a Node web application. You have learned the importance of validating user input and how to do that using Joi. You also made use of bcryptjs to salt and hash your password.

Next, you'll see how to implement a login feature for registered users. I trust you enjoyed yourself!

Categories: Web Design

Creating a Task Manager App Using Ionic: Part 2

Wed, 12/20/2017 - 05:00

In the first part of the tutorial series, you created the user interface and navigation for the task manager app. In this tutorial, you'll see how to implement the functionality for the Ionic task manager app to add and list tasks.

Getting Started

Let's get started by cloning the source code from the first part of the tutorial series.

git clone https://github.com/royagasthyan/IonicTaskManager-Part1

Navigate to the project directory and install the required dependencies.

cd IonicTaskManager-Part1 npm install

Run your app from the project directory.

ionic serve

You should have the application running at http://localhost:8100/.

Communicating Between Components

You have already created the Add component and List component to add tasks and to list tasks respectively. In order to make them work in sync, you need to maintain communication between the two components. To communicate between the components, you'll make use of an injectable CommonService.  

Create a folder called service in the src/pages folder.

Create a service file called common.service.ts and add the following code:

import { Injectable } from '@angular/core'; @Injectable() export class CommonService { constructor(){ this.tasks = [] } }

You'll keep track of the tasks list in the common service, and it will be shared between the Add and List components.

Define a variable called tasks in the common.service.ts file. You'll keep your task list in this tasks array.

import { Injectable } from '@angular/core'; @Injectable() export class CommonService { public tasks:any; constructor(){ this.tasks = [] } }

Create a folder called task inside the src/pages folder. Create a file called task.model.ts and add the following code:

export class Task{ constructor( public Id: Number, public Name: String, public IsDone: Boolean ) { } }

You'll use the above Task class to create an instance of a new task.

When the user clicks on the Add task button from the Add component, you'll add items to the tasks variable in the common.service.ts file. So create a method called addTask in the common.service.ts file, which you'll call from the Add component.

import { Injectable } from '@angular/core'; import { Task } from '../model/task.model' @Injectable() export class CommonService { public tasks:any; constructor(){ this.tasks = [] } addTask(item){ this.tasks.push(new Task((new Date()).getTime(),item,false)); } }Add a Task to the List

In order to add a task to the task list, you need to import the common.service.ts file inside the AddPage component.

import { CommonService } from '../service/common.service'

Initialize the CommonService inside the AddPage component constructor method.

constructor(public viewCtrl: ViewController, private commonService: CommonService) { }

Inside the AddPage component, create a method called add where you'll add the task to the common service tasks list.

Here is how the add method in the AddPage component looks:

add(){ this.commonService.addTask(this.item); this.dismiss(); }

As seen in the above method, you have called the addTask method from the common service to add a task to the tasks list.

Once the item is added, you have called the dismiss method to dismiss the pop-up overlay. Here is how the add.component.ts file looks:

import { Component } from '@angular/core'; import { ViewController } from 'ionic-angular'; import { CommonService } from '../service/common.service' @Component({ selector: 'page-add', templateUrl: 'add.component.html' }) export class AddPage { public tasks: any = []; public item:String; constructor(public viewCtrl: ViewController, private commonService: CommonService) { } dismiss(){ this.viewCtrl.dismiss(); } add(){ this.commonService.addTask(this.item); this.dismiss(); } }

In the add.component.html page, add the ngModel directive to the input element.

<ion-input name="add" [(ngModel)]="item"></ion-input>

Add the click event to the button in the add.component.html to trigger the add method inside the add.component.ts.

<button ion-button round (click)="add()">Add</button>

Save the above changes and try to restart the ionic server. Navigate the browser URL to http://localhost:8100, and you should be able to view the mobile app in the browser.

Click on the Add icon to add a task. Enter the task name and click the add button. The pop-up should disappear.

Listing Task List Items

Once the task gets added in the tasks list, you need to update the view accordingly. So, to track the task when added to the list, you'll need to use Angular Subject.

Define a subject called task_subject inside the common.service.ts file.

public task_subject = new Subject<String>()

When the task gets added to the tasks list, you need to trigger the subject task_subject to inform the subscriber that a task has been added.

Modify the addTask method inside the common.service.ts file to include the following code:

this.task_subject.next();

Here is the modified addTask method:

addTask(item){ this.tasks.push(new Task((new Date()).getTime(),item,false)); this.task_subject.next(); }

Subscribe to the subject task_subject inside the list.component.ts file.

constructor(public modalCtrl: ModalController, public commonService:CommonService) { this.commonService.task_subject.subscribe(response => { this.tasks = this.commonService.tasks; }) }

Whenever a new task is added the tasks from the commonService is assigned to the tasks in list.component.html and the view is updated.

Here is how the list.component.ts code looks:

import { Component } from '@angular/core'; import { ModalController } from 'ionic-angular'; import { AddPage } from '../add/add.component'; import { CommonService } from '../service/common.service' @Component({ selector: 'page-list', templateUrl: 'list.component.html' }) export class ListPage { public tasks=[]; constructor(public modalCtrl: ModalController, public commonService:CommonService) { this.commonService.task_subject.subscribe(response => { this.tasks = this.commonService.tasks; }) } presentAddModal() { let addModal = this.modalCtrl.create(AddPage); addModal.present(); } }

Modify the list.component.html to iterate over the tasks variable from the list.component.ts file. Here is how it looks: 

<ion-list> <ion-item *ngFor="let item of tasks"> <ion-label>{{item.Name}} </ion-label> <ion-checkbox name="chk"></ion-checkbox> </ion-item> </ion-list>

Save the above changes and restart the server. Try to add a new task and it will get displayed on the listing screen.

Now let's implement the functionality to mark the finished tasks. Each time a new task is added, you are adding an IsDone attribute as false.

Let's keep two different arrays for pending tasks and finished tasks.

public pendingTasks = [] public doneTasks = []

Each time a new task is added, you'll update the above two arrays as shown:

constructor(public modalCtrl: ModalController, public commonService:CommonService) { this.commonService.task_subject.subscribe(response => { this.pendingTasks = this.commonService.tasks.filter(item => { return item.IsDone == false }); this.doneTasks = this.commonService.tasks.filter(item => { return item.IsDone == true }); }) }

When the user clicks on the check box, you need to toggle the IsDone status. Add a method called checkPendingItem to toggle the IsDone status for pending tasks.

checkPendingItem(id){ this.pendingTasks.map((task) => { if(task.Id == id){ if(task.IsDone){ task.IsDone = false; } else{ task.IsDone = true; } } }) this.updateTask() }

Similarly, add another method called checkDoneItem to toggle the task status for done items. Here is how the method looks:

checkDoneItem(id){ this.doneTasks.map((task) => { if(task.Id == id){ if(task.IsDone){ task.IsDone = false; } else{ task.IsDone = true; } } }) this.updateTask() }

Once the IsDone status is toggled, you need to update the tasks. Define a method called updateTask, which is called after IsDone toggle in both of the above methods.

updateTask(){ this.pendingTasks = this.commonService.tasks.filter(item => { return item.IsDone == false }); this.doneTasks = this.commonService.tasks.filter(item => { return item.IsDone == true }); }

Modify the list.component.html code to display the pendingTasks and doneTasks separately. Here is how the modified list.component.html file looks:

<ion-header> <ion-navbar> <ion-title text-center>Ionic Task Manager</ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-fab top right> <button ion-fab mini (click)="presentAddModal()"><ion-icon name="add"></ion-icon></button> </ion-fab> <ion-card> <ion-card-header> My Tasks </ion-card-header> <ion-list> <ion-item *ngFor="let item of pendingTasks"> <ion-label>{{item.Name}} </ion-label> <ion-checkbox name="chk" (click)="checkPendingItem(item.Id)" [checked]="item.IsDone"></ion-checkbox> </ion-item> </ion-list> </ion-card> <ion-card> <ion-card-header> Archived Tasks </ion-card-header> <ion-list> <ion-item *ngFor="let item of doneTasks"> <ion-label color="light">{{item.Name}} </ion-label> <ion-checkbox name="chk" (click)="checkDoneItem(item.Id)" [checked]="item.IsDone"></ion-checkbox> </ion-item> </ion-list> </ion-card> </ion-content>

Save the above changes and restart the ionic server. You should have the application running at http://localhost:8100.

Wrapping It Up 

In this tutorial, you saw how to implement the functionality to add and list the tasks in the Ionic task manager mobile app. You saw how to use an Angular service to share data between two components. In this tutorial, you used the Angular service to keep data in a common list when added from the Add component and display it in the List component.

Do let us know your thoughts in the comments below.

Source code from this tutorial is available on GitHub.

Categories: Web Design

Creating a Task Manager App Using Ionic: Part 1

Tue, 12/19/2017 - 05:00

In this tutorial series, you'll learn how to get started with creating a mobile app using the Ionic framework. Ionic uses Angular for writing the components and creating the mobile app. 

Throughout the course of this series, you'll be creating a simple task manager mobile app using the Ionic framework.

From the official documentation:

Ionic is the beautiful, free and open source mobile SDK for developing native and progressive web apps with ease. Getting Started

Let's get started by installing Ionic using Node Package Manager (npm). Before installing Ionic, make sure you have Node.js installed on your system.

npm install -g cordova ionic

Once Ionic has been installed, create a new Ionic blank project using the following command:

ionic start angular-ionic blank

You'll be testing the Ionic app in the browser until it's complete. Once complete, you'll test the application on an Android device.

Type in the following command to run the app from the browser.

ionic serve

Point your browser to http://localhost:8100/ and you should have the Ionic project running.

Here is how the project structure looks:

Inside the Ionic project, you have a folder called src/app. Inside the app folder, you will find a file called app.module.ts where the root module AppModule is defined.

In the app.module.ts file inside the imports section, you can see that the root component has been defined using the following code:

IonicModule.forRoot(MyApp)

MyApp has been imported from the app.component where it has set the rootPage as HomePage, which shows up when the app loads.

Creating a List Task Component

Let's create the view for listing the added tasks. Inside the src/pages folder, create another folder for the list component called list.

Inside the list folder, create a file called list.component.html which would be the component template. Add the following code to the list.component.html file:

<ion-header> <ion-navbar> <ion-title>Ionic Task List</ion-title> </ion-navbar> </ion-header> <ion-content> <ion-list> <ion-item> <ion-label>Task 1 </ion-label> <ion-checkbox></ion-checkbox> </ion-item> <ion-item> <ion-label>Task 2</ion-label> <ion-checkbox></ion-checkbox> </ion-item> <ion-item> <ion-label>Task 3 </ion-label> <ion-checkbox></ion-checkbox> </ion-item> </ion-list> </ion-content>

As seen in the code above, you have used Ionic-specific tags for creating the elements. You can refer to the Ionic official documentation to get a list of Ionic component APIs which you can use while creating your templates.

To control the above created template, you'll need a controller class. Create a file called list.component.ts and define the ListPage class. Here is how it looks:

import { Component } from '@angular/core'; @Component({ selector: 'page-list', templateUrl: 'list.component.html' }) export class ListPage { constructor() { } }

You have defined the task listing component using the @Component decorator. Inside the @Component decorator, you have defined the selector using the selector key and the template using the templateUrl key for the component.

The application needs to know that the above created component exists, and hence you need to import it inside the root module.

Import the ListPage class inside the src/app/app.module.ts file and include it in the declarations and entryComponents list. Here is how the modified app.module.ts file looks:

import { BrowserModule } from '@angular/platform-browser'; import { ErrorHandler, NgModule } from '@angular/core'; import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular'; import { SplashScreen } from '@ionic-native/splash-screen'; import { StatusBar } from '@ionic-native/status-bar'; import { ListPage } from '../pages/list/list.component'; import { MyApp } from './app.component'; import { HomePage } from '../pages/home/home'; @NgModule({ declarations: [ MyApp, HomePage, ListPage ], imports: [ BrowserModule, IonicModule.forRoot(MyApp) ], bootstrap: [IonicApp], entryComponents: [ MyApp, HomePage, ListPage ], providers: [ StatusBar, SplashScreen, {provide: ErrorHandler, useClass: IonicErrorHandler} ] }) export class AppModule {}

When the application loads up, you want the newly created List component to show up instead of the HomePage. So modify the rootPage defined inside the app.component.ts file. 

import { Component } from '@angular/core'; import { Platform } from 'ionic-angular'; import { StatusBar } from '@ionic-native/status-bar'; import { SplashScreen } from '@ionic-native/splash-screen'; import { HomePage } from '../pages/home/home'; import { ListPage } from '../pages/list/list.component'; @Component({ templateUrl: 'app.html' }) export class MyApp { rootPage:any = ListPage; constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) { platform.ready().then(() => { statusBar.styleDefault(); splashScreen.hide(); }); } }

As seen in the above code, you imported the ListPage inside the app.component.ts file and changed the rootPage to ListPage instead of HomePage.

Save the above changes and start the Ionic server using the following command:

ionic serve

You should have the mobile app running at http://localhost:8100/

Creating the Add Task Component

From the listing screen, you'll add a link to add items to the list. Let's place an add icon on the right side of the screen. Inside the list.component.html file, add the following to add the plus icon.

<ion-fab top right> <button ion-fab mini><ion-icon name="add"></ion-icon></button> </ion-fab>

Here is how the modified list.component.html file looks:

<ion-header> <ion-navbar> <ion-title text-center>Ionic Task Manager</ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-fab top right> <button ion-fab mini><ion-icon name="add"></ion-icon></button> </ion-fab> <ion-list> <ion-item> <ion-label>Task 1 </ion-label> <ion-checkbox></ion-checkbox> </ion-item> <ion-item> <ion-label>Task 2</ion-label> <ion-checkbox></ion-checkbox> </ion-item> <ion-item> <ion-label>Task 3 </ion-label> <ion-checkbox></ion-checkbox> </ion-item> </ion-list> </ion-content>

Save the above changes and restart the server, and you will have the plus icon displayed on the screen.

When the user clicks on the plus icon, you need to show the screen to add new tasks. So let's create another component called the Add component.

Create a folder called add inside the pages folder. Inside the add folder, create a file called add.component.html and add the following code:

<ion-header> <ion-navbar> <ion-title text-center>Ionic Task Manager</ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-fab top right> <button ion-fab mini> <ion-icon name="arrow-back"></ion-icon></button> </ion-fab> <ion-list> <ion-item> <ion-label color="primary" floating>Enter task </ion-label> <ion-input></ion-input> </ion-item> </ion-list> <button ion-button round>Add</button> </ion-content>

The above code displays the screen to add a new task.

You need to display the above screen when the user clicks the plus icon on the list screen. So you'll be showing it as a modal popup.

Create a file called add.component.ts and add the following code:

import { Component } from '@angular/core'; @Component({ selector: 'page-add', templateUrl: 'add.component.html' }) export class AddPage { constructor() { } }

As seen in the above code, you just created the Add component by specifying the selector and templateUrl.

Register the component by importing it in the app.module.ts file inside the src/app folder. Here is how the modified app.module.ts file looks:

import { BrowserModule } from '@angular/platform-browser'; import { ErrorHandler, NgModule } from '@angular/core'; import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular'; import { SplashScreen } from '@ionic-native/splash-screen'; import { StatusBar } from '@ionic-native/status-bar'; import { ListPage } from '../pages/list/list.component'; import { AddPage } from '../pages/add/add.component'; import { MyApp } from './app.component'; import { HomePage } from '../pages/home/home'; @NgModule({ declarations: [ MyApp, HomePage, ListPage, AddPage ], imports: [ BrowserModule, IonicModule.forRoot(MyApp) ], bootstrap: [IonicApp], entryComponents: [ MyApp, HomePage, ListPage, AddPage ], providers: [ StatusBar, SplashScreen, {provide: ErrorHandler, useClass: IonicErrorHandler} ] }) export class AppModule {}

To show the AddPage component in a modal popup, you need to import ModalController provided by ionic-angular. Import ModalController in list.component.ts.

import { ModalController } from 'ionic-angular';

Create a method called presentAddModal and create a modal using the imported ModalController. Here is how the list.component.ts file looks:

import { Component } from '@angular/core'; import { ModalController } from 'ionic-angular'; import { AddPage } from '../add/add.component'; @Component({ selector: 'page-list', templateUrl: 'list.component.html' }) export class ListPage { constructor(public modalCtrl: ModalController) {} presentAddModal() { let addModal = this.modalCtrl.create(AddPage); addModal.present(); } }

Register the click event on the add button in list.component.html. 

<button ion-fab mini (click)="presentAddModal()"><ion-icon name="add"></ion-icon></button>

Save the above changes and restart the Ionic server. Click on the add icon in the list page and you will have the add task page.

For the back button on the add task screen, you need to add a dismiss method on the button click in the add.component.ts file.

<button ion-fab mini (click)="dismiss()"> <ion-icon name="arrow-back"></ion-icon></button>

Import the ViewController module and call the dismiss method to go back to the listing screen. Here is how it looks:

import { Component } from '@angular/core'; import { ViewController } from 'ionic-angular'; @Component({ selector: 'page-add', templateUrl: 'add.component.html' }) export class AddPage { constructor(public viewCtrl: ViewController) { } dismiss(){ this.viewCtrl.dismiss(); } } Wrapping It Up

In this tutorial, you saw how to get started with creating a mobile app using the Ionic framework, which uses Angular. You created the view for a task manager app. You created the Add component and List component. 

In the next part of this tutorial series, you'll implement the functionality for the task manager app to add and list tasks.

Source code from this tutorial is available on GitHub.

Do let us know your suggestions in the comments below.

Categories: Web Design

Introduction to Forms in Angular 4: Reactive Forms

Tue, 12/19/2017 - 04:00
What You'll Be Creating

This is the second part of the series on Introduction to Forms in Angular 4. In the first part, we created a form using the template-driven approach. We used directives such as ngModel, ngModelGroup and ngForm to supercharge the form elements. In this tutorial, we will be taking a different approach to building forms—the reactive way. 

Reactive Forms

Reactive forms take a different approach compared to that of the template-driven forms. Here, we create and initialize the form control objects in our component class. They are intermediate objects that hold the state of the form. We will then bind them to the form control elements in the template.

The form control object listens to any change in the input control values, and they are immediately reflected in the object's state. Since the component has direct access to the data model structure, all changes can be synchronized between the data model, the form control object, and the input control values. 

Practically speaking, if we are building a form for updating the user profile, the data model is the user object retrieved from the server. By convention, this is often stored inside the component's user property (this.user). The form control object or the form model will be bound to the template's actual form control elements.

Both these models should have similar structures, even if they are not identical. However, the input values shouldn't flow into the data model directly. The image describes how the user input from the template makes its way to the form model.

Let's get started.

Prerequisites

You don’t need to have followed part one of this series, for part two to make sense. However, if you are new to forms in Angular, I would highly recommend going through the template-driven strategy. The code for this project is available on my GitHub repository. Make sure that you are on the right branch and then download the zip or, alternatively, clone the repo to see the form in action. 

If you prefer to start from scratch instead, make sure that you have Angular CLI installed. Use the ng command to generate a new project. 

$ ng new SignupFormProject

Next, generate a new component for the SignupForm or create one manually. 

ng generate component SignupForm

Replace the contents of app.component.html with this:

<app-signup-form> </app-signup-form>

Here is the directory structure for the src/ directory. I've removed some non-essential files to keep things simple.

. ├── app │   ├── app.component.css │   ├── app.component.html │   ├── app.component.ts │   ├── app.module.ts │   ├── signup-form │   │   ├── signup-form.component.css │   │   ├── signup-form.component.html │   │   └── signup-form.component.ts │   └── User.ts ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css ├── tsconfig.app.json └── typings.d.ts

As you can see, a directory for the SignupForm component has been created automatically. That's where most of our code will go. I've also created a new User.ts for storing our User model.

The HTML Template

Before we dive into the actual component template, we need to have an abstract idea of what we are building. So here is the form structure that I have in my mind. The signup form will have several input fields, a select element, and a checkbox element. 


Here is the HTML template that we will be using for our registration page. 

HTML Template <div class="row custom-row"> <div class= "col-sm-5 custom-container jumbotron"> <form class="form-horizontal"> <fieldset> <legend>SignUp</legend> <!--- Email Block ---> <div class="form-group"> <label for="inputEmail">Email</label> <input type="text" id="inputEmail" placeholder="Email"> </div> <!--- Password Block ---> <div class="form-group"> <label for="inputPassword">Password</label> <input type="password" id="inputPassword" placeholder="Password"> </div> <div class="form-group"> <label for="confirmPassword" >Confirm Password</label> <input type="password" id="confirmPassword" placeholder="Password"> </div> <!--- Select gender Block ---> <div class="form-group"> <label for="select">Gender</label> <select id="select"> <option>Male</option> <option>Female</option> <option>Other</option> </select> </div> <!--- Terms and conditions Block ---> <div class="form-group checkbox"> <label> <input type="checkbox"> Confirm that you've read the Terms and Conditions </label> </div> <!--- Buttons Block ---> <div class="form-group"> <button type="reset" class="btn btn-default">Cancel</button> <button type="submit" class="btn btn-primary">Submit</button> </div> </fieldset> </form> </div> </div>

The CSS classes used in the HTML template are part of the Bootstrap library used for making things pretty. Since this is a not a design tutorial, I won't be talking much about the CSS aspects of the form unless necessary. 

Basic Form Setup

To create a Reactive form, you need to import  the ReactiveFormsModule from @angular/forms and add it to the imports array in app.module.ts.

app/app.module.ts// Import ReactiveFormsModule import { ReactiveFormsModule } from '@angular/forms'; @NgModule({ . . //Add the module to the imports Array imports: [ BrowserModule, ReactiveFormsModule . . }) export class AppModule { }

Next, create a User model for the registration form. We can either use a class or an interface for creating the model. For this tutorial, I am going to export a class with the following properties.

app/User.tsexport class User { id: number; email: string; //Both the passwords are in a single object password: { pwd: string; confirmPwd: string; }; gender: string; terms: boolean; constructor(values: Object = {}) { //Constructor initialization Object.assign(this, values); } }

Now, create an instance of the User model in the SignupForm component. 

app/signup-form/signup-form.component.tsimport { Component, OnInit } from '@angular/core'; // Import the User model import { User } from './../User'; @Component({ selector: 'app-signup-form', templateUrl: './signup-form.component.html', styleUrls: ['./signup-form.component.css'] }) export class SignupFormComponent implements OnInit { //Gender list for the select control element private genderList: string[]; //Property for the user private user:User; ngOnInit() { this.genderList = ['Male', 'Female', 'Others']; }

For the signup-form.component.html file, I am going to use the same HTML template discussed above, but with minor changes. The signup form has a select field with a list of options. Although that works, we will do it the Angular way by looping through the list using the ngFor directive.

app/signup-form/signup-form.component.html<div class="row custom-row"> <div class= "col-sm-5 custom-container jumbotron"> <form class="form-horizontal"> <fieldset> <legend>SignUp</legend> . . <!--- Gender Block --> <div class="form-group"> <label for="select">Gender</label> <select id="select"> <option *ngFor = "let g of genderList" [value] = "g"> {{g}} </option> </select> </div> . . </fieldset> </form> </div> </div>

Note: You might get an error that says No provider for ControlContainer. The error appears when a component has a <form> tag without a formGroup directive. The error will disappear once we add a FormGroup directive later in the tutorial.

We have a component, a model, and a form template at hand. What now? It's time to get our hands dirty and become acquainted with the APIs that you need to create reactive forms. This includes FormControl and FormGroup. 

Tracking the State Using FormControl

While building forms with the reactive forms strategy, you won't come across the ngModel and ngForm directives. Instead, we use the underlying FormControl and FormGroup API.

A FormControl is a directive used to create a FormControl instance that you can use to keep track of a particular form element's state and its validation status. This is how FormControl works:

/* Import FormControl first */ import { FormControl } from '@angular/forms'; /* Example of creating a new FormControl instance */ export class SignupFormComponent { email = new FormControl(); }

email is now a FormControl instance, and you can bind it to an input control element in your template as follows:

<h2>Signup</h2> <label class="control-label">Email: <input class="form-control" [formControl]="email"> </label>

The template form element is now bound to the FormControl instance in the component. What that means is any change to the input control value gets reflected at the other end. 

A FormControl constructor accepts three arguments—an initial value, an array of sync validators, and an array of async validators—and as you might have guessed, they are all optional. We will be covering the first two arguments here. 

import { Validators } from '@angular/forms'; . . . /* FormControl with initial value and a validator */ email = new FormControl('bob@example.com', Validators.required);

Angular has a limited set of built-in validators. The popular validator methods include Validators.required, Validators.minLength, Validators.maxlength, and Validators.pattern. However, to use them, you have to import the Validator API first.

For our signup form, we have multiple input control fields (for email and password), a selector field, and a checkbox field. Rather than creating individual FormControl objects, wouldn't it make more sense to group all these FormControls under a single entity? This is beneficial because we can now track the value and the validity of all the sub-FormControl objects in one place. That's what FormGroup is for. So we will register a parent FormGroup with multiple child FormControls. 

Group Multiple FormControls With FormGroup

To add a FormGroup, import it first. Next, declare signupForm as a class property and initialize it as follows:

app/signup-form/signup-form.component.ts//Import the API for building a form import { FormControl, FormGroup, Validators } from '@angular/forms'; export class SignupFormComponent implements OnInit { genderList: String[]; signupForm: FormGroup; . . ngOnInit() { this.genderList = ['Male', 'Female', 'Others']; this.signupForm = new FormGroup ({ email: new FormControl('',Validators.required), pwd: new FormControl(), confirmPwd: new FormControl(), gender: new FormControl(), terms: new FormControl() }) } }

Bind the FormGroup model to the DOM as follows: 

app/signup-form/signup-form.component.html <form class="form-horizontal" [formGroup]="signupForm" > <fieldset> <legend>SignUp</legend> <!--- Email Block --> <div class="form-group"> <label for="inputEmail">Email</label> <input type="text" formControlName = "email" id="inputEmail" placeholder="Email"> . . </fieldset> </form>

[formGroup] = "signupForm" tells Angular that you want to associate this form with the FormGroup declared in the component class. When Angular sees formControlName="email", it checks for an instance of FormControl with the key value email inside the parent FormGroup. 

Similarly, update the other form elements by adding a formControlName="value" attribute as we just did here.

To see if everything is working as expected, add the following after the form tag:

app/signup-form/signup-form.component.html<!--- Log the FormGroup values to see if the binding is working --> <p>Form value {{ signupForm.value | json }} </p> <p> Form status {{ signupForm.status | json}} </p>

Pipe the SignupForm property through the JsonPipe to render the model as JSON in the browser. This is helpful for debugging and logging. You should see a JSON output like this.

There are two things to note here:

  1. The JSON doesn't exactly match the structure of the user model that we created earlier. 
  2. The signupForm.status displays that the status of the form is INVALID. This clearly shows that the Validators.required on the email control field is working as expected. 

The structure of the form model and the data model should match. 

// Form model { "email": "", "pwd": "", "confirmPwd": "", "gender": "", "terms": false } //User model { "email": "", "password": { "pwd": "", "confirmPwd": "", }, "gender": "", "terms": false }

To get the hierarchical structure of the data model, we should use a nested FormGroup. Additionally, it's always a good idea to have related form elements under a single FormGroup. 

Nested FormGroup

Create a new FormGroup for the password.

app/signup-form/signup-form.component.ts
this.signupForm = new FormGroup ({ email: new FormControl('',Validators.required), password: new FormGroup({ pwd: new FormControl(), confirmPwd: new FormControl() }), gender: new FormControl(), terms: new FormControl() })

Now, to bind the new form model with the DOM, make the following changes:

app/signup-form/signup-form.component.html<!--- Password Block --> <div formGroupName = "password"> <div class="form-group"> <label for="inputPassword">Password</label> <input type="password" formControlName = "pwd" id="inputPassword" placeholder="Password"> </div> <div class="form-group"> <label for="confirmPassword" >Confirm Password</label> <input type="password" formControlName = "confirmPwd" id="confirmPassword" placeholder="Password"> </div> </div>

formGroupName = "password" performs the binding for the nested FormGroup. Now, the structure of the form model matches our requirements.

Form value: { "email": "", " password": { "pwd": null, "confirmPwd": null }, "gender": null, "terms": null } Form status "INVALID"

Next up, we need to validate the form controls.

Validating the Form

We have a simple validation in place for the email input control. However, that's not sufficient. Here is the entire list of our requirements for the validation.

  • All form control elements are required.
  • Disable the submit button until the status of the form is VALID.
  • The email field should strictly contain an email id.
  • The password field should have a minimum length of 8.

The first one is easy. Add Validator.required to all the FormControls in the form model. 

app/signup-form/signup-form.component.ts  this.signupForm = new FormGroup ({ email: new FormControl('',Validators.required), password: new FormGroup({ pwd: new FormControl('', Validators.required), confirmPwd: new FormControl('', Validators.required) }), gender: new FormControl('', Validators.required), //requiredTrue so that the terms field isvalid only if checked terms: new FormControl('', Validators.requiredTrue) })

Next, disable the button while the form is INVALID.

app/signup-form/signup-form.component.html<!--- Buttons Block --> <div class="form-group"> <button type="reset" class="btn btn-default">Cancel</button> <button type="submit" [disabled] = "!signupForm.valid" class="btn btn-primary">Submit</button> </div>

To add a constraint on email, you can either use the default Validators.email or create a custom Validators.pattern() that specifies regular expressions like the one below:

email: new FormControl('', [Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$')])

Use the minLength validator for the password fields.

password: new FormGroup({ pwd: new FormControl('', [Validators.required, Validators.minLength(8)]), confirmPwd: new FormControl('', [Validators.required, Validators.minLength(8)]) }),

That's it for the validation. However, the form model logic appears cluttered and repetitive. Let's clean that up first. 

Refactoring the Code Using FormBuilder

Angular provides you with a syntax sugar for creating new instances of FormGroup and FormControl called FormBuilder. The FormBuilder API doesn't do anything special other than what we've covered here.

It simplifies our code and makes the process of building a form easy on the eyes. To create a FormBuilder, you have to import it into signup-form.component.ts and inject the FormBuilder into the constructor.

app/signup-form/signup-form.component.ts import { FormBuilder, FormGroup, Validators } from '@angular/forms'; . . export class SignupFormComponent implements OnInit { signupForm: FormGroup; // Declare the signupForm //Inject the formbuilder into the constructor constructor(private fb:FormBuilder) {} ngOnInit() { ... } }

Instead of a creating a new FormGroup(), we are using this.fb.group to build a form. Except for the syntax, everything else remains the same.

app/signup-form/signup-form.component.ts  ngOnInit() { ... this.signupForm = this.fb.group({ email: ['',[Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$')]], password: this.fb.group({ pwd: ['', [Validators.required, Validators.minLength(8)]], confirmPwd: ['', [Validators.required, Validators.minLength(8)]] }), gender: ['', Validators.required], terms: ['', Validators.requiredTrue] }) }Displaying Validation Errors 

For displaying the errors, I am going to use the conditional directive ngIf on a div element. Let's start with the input control field for email:

<!-- Email error block --> <div *ngIf="signupForm.controls.email.invalid && signupForm.controls.email.touched" Email is invalid </div>

There are a couple of issues here. 

  1. Where did invalid and pristine come from? 
  2. signupForm.controls.email.invalid is too long and deep.
  3. The error doesn't explicitly say why it's invalid.

To answer the first question, each FormControl has certain properties like invalid, valid, pristine, dirty, touched, and untouched. We can use these to determine whether an error message or a warning should be displayed or not. The image below describes each of those properties in detail.

So the div element with the *ngIf will be rendered only if the email is invalid. However, the user will be greeted with errors about the input fields being blank even before they have a chance to edit the form. 

To avoid this scenario, we've added the second condition. The error will be displayed only after the control has been visited.

To get rid of the long chain of method names (signupForm.controls.email.invalid), I am going to add a couple of shorthand getter methods. This keeps them more accessible and short. 

app/signup-form/signup-form.component.ts export class SignupFormComponent implements OnInit { ... get email() { return this.signupForm.get('email'); } get password() { return this.signupForm.get('password'); } get gender() { return this.signupForm.get('gender'); } get terms() { return this.signupForm.get('terms'); } }

To make the error more explicit, I've added nested ngIf conditions below:

app/signup-form/signup-form.component.html<!-- Email error block --> <div *ngIf="email.invalid && email.touched" class="col-sm-3 text-danger"> <div *ngIf = "email.errors?.required"> Email field can't be blank </div> <div *ngIf = "email.errors?.pattern"> The email id doesn't seem right </div> </div>

We use email.errors to check all possible validation errors and then display them back to the user in the form of custom messages. Now, follow the same procedure for the other form elements. Here is how I've coded the validation for the passwords and the terms input control.

app/signup-form/signup-form.component.html <!-- Password error block --> <div *ngIf="(password.invalid && password.touched)" class="col-sm-3 text-danger"> Password needs to be more than 8 characters </div> . . . <!--- Terms error block --> <div *ngIf="(terms.invalid && terms.touched)" class="col-sm-3 text-danger"> Please accept the Terms and conditions first. </div> </div>Submit the Form Using ngSubmit

We are nearly done with the form. It lacks the submit functionality, which we are about to implement now.

<form class="form-horizontal" [formGroup]="signupForm" (ngSubmit)="onFormSubmit()" >

On form submit, the form model values should flow into the component's user property.

app/signup-form/signup-form.component.tspublic onFormSubmit() { if(this.signupForm.valid) { this.user = this.signupForm.value; console.log(this.user); /* Any API call logic via services goes here */ } }Final Demo

Here is the final version of the application. I've added a few Bootstrap classes to make the form pretty.

Wrapping It Up

If you've been following this tutorial series from the start, we had a hands-on experience with two popular form building technologies in Angular. The template-driven and model-driven techniques are two ways of achieving the same thing. Personally, I prefer to use the reactive forms for the following reasons:

  • All the form validation logic will be located in a single place—inside your component class. This is way more productive than the template approach, where the ngModel directives are scattered across the template.
  • Unlike template-driven forms, Model-driven forms are easier to test. You don't have to resort to end-to-end testing libraries to test your form.
  • Validation logic will go inside the component class and not in the template.
  • For a form with a large number of form elements, this approach has something called FormBuilder to make the creation of FormControl objects easier.

We missed out on one thing, and that is writing a validator for the password mismatch. In the final part of the series, we will cover everything you need to know about creating custom validator functions in Angular. Stay tuned until then.

In the meantime, there are plenty of frameworks and libraries to keep you busy, with lots of items on Envato Market to read, study, and use.

Categories: Web Design

Deferring Tasks in Laravel Using Queues

Mon, 12/18/2017 - 05:00

In this article, we're going to explore the Queue API in the Laravel web framework. It allows you to defer resource-intensive tasks during script execution to enhance the overall end user experience. After introducing the basic terminology, I'll demonstrate it by implementing a real-world example.

Page load time is an important aspect of any successful website, and one should not overlook the importance of that as it affects the SEO of the site and the overall end user experience as well. More often than not, you end up needing to debug web pages with long page load times. Of course, there are different approaches you could use to rectify this issue.

Upon investigation, you often realize that there are certain code blocks causing a delay in the page execution. The next thing you could try is identifying blocks that can be deferred for processing and that have no real impact on the end result of the current page. That should really improve the overall web page speed as we've eliminated code blocks that were causing a delay.

Today, we're going to explore a similar concept in the context of the Laravel web framework. In fact, Laravel already provides a useful built-in API that allows us to defer the processing of tasks—the Queue API. Without wasting much of your time, I'll go ahead and discuss the basic elements of the Queue API.

Drivers, Connections, Queues, and Jobs

The basic purpose of the Queue API is to run jobs that are added in a queue. Next, the queue could belong to a specific connection, and that connection may belong to a specific queue driver configured with that connection itself. Let's briefly try to understand what I've just said.

Queue Drivers

In the same way you would have used a different driver for your database connection, you could also choose from a variety of different queue drivers. The Queue API supports different adapters like database, beanstalkd, sqs, and redis.

The queue driver is just a place that is used to store queue-related information. So if you're using a database queue driver, for example, the new job will be added in the jobs table in the database. On the other hand, if you've configured redis as the default queue driver, the job will be added to the redis server.

The Queue API also provides two special queue drivers for testing purposes—sync and null. The sync queue driver is used to execute a queue job immediately, while the null queue driver is used to skip a job so that it won't be executed at all.

Connections

When you configure the Queue API for the first time, you need to specify a default connection that should be used for default queue processing. At the very least, the connection is expected to provide the following information:

  • the queue driver that will be used
  • the queue driver's specific configuration values
  • the default queue name in which the job will be added
Queues

When you add any job into a queue, it'll be added into the default queue. In fact, that should be fine in most cases, unless you have jobs that need to be given higher priority over other jobs. In that case, you could create a queue named high and place the higher priority jobs in that particular queue.

When you run a queue worker that processes queued jobs, you could optionally pass the --queue parameter, which allows you to list queue names in the order in which they need to be processed. For example, if you specify --queue=high,default, it will first process jobs in the high queue, and once it's completed it fetches jobs in the default queue.

Jobs

A job in the Queue API is a task that's deferred from the main execution flow. For example, if you want to create a thumbnail when the user uploads an image from the front-end, you could create a new job that handles the thumbnail processing. In this way, you could defer the task of thumbnail processing from the main execution flow.

That was a basic introduction to the Queue API terminology. From the next section onwards, we'll explore how to create a custom queue job and run it by using a Laravel queue worker.

Create Your First Queue Job

By now, you should feel confident about queue jobs. From this section onwards, we're going to implement a real-world example that demonstrates the concept of queue jobs in Laravel.

More often than not, you end up in the situation where you need to create different thumbnail versions of an image uploaded by a user. In most cases, the developer tries to process it in real time so that different versions of images are created right away when the user uploads an image.

It seems to be a reasonable approach if you're going to create a couple of versions and it doesn't take too much time in the first place. On the other hand, if you're dealing with an application that requires heavy processing and thus eats up more resources, real-time processing could end up in a bad user experience.

The obvious option that pops up in your mind in the first place is to defer processing of the thumbnail generation as late as possible. The simplest approach you could implement in this specific scenario is to set a cron job that triggers processing at regular intervals, and you should be fine.

A much better approach, on the other hand, is to defer and push the task into a queue, and let the queue worker process it when it gets a chance to do so. In a production environment, the queue worker is a daemon script that's always running and processing tasks in a queue. The obvious benefit of this approach is a much better end user experience, and you don't have to wait for the cron run as the job will be processed as soon as possible.

I guess that's enough theory to get started with an actual implementation.

In our case, we're going to use the database queue driver, and it requires us to create the jobs table in the database. The jobs table holds all the jobs that need to be processed in the next queue worker run.

Before we go ahead and create the jobs table, let's change the default queue configuration from sync to database in the config/queue.php file.

... ... /* |-------------------------------------------------------------------------- | Default Queue Driver |-------------------------------------------------------------------------- | | Laravel's queue API supports an assortment of back-ends via a single | API, giving you convenient access to each back-end using the same | syntax for each one. Here you may set the default queue driver. | | Supported: "sync", "database", "beanstalkd", "sqs", "redis", "null" | */ 'default' => env('QUEUE_DRIVER', 'database'), ... ...

In fact, Laravel already provides an artisan command that helps us to create the jobs table. Run the following command in the root of your Laravel application, and it should create the necessary database migration that creates the jobs table.

$php artisan queue:table

The migration file that's generated at database/migrations/YYYY_MM_DD_HHMMSS_create_jobs_table.php should look like this:

<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateJobsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('jobs', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('queue'); $table->longText('payload'); $table->unsignedTinyInteger('attempts'); $table->unsignedInteger('reserved_at')->nullable(); $table->unsignedInteger('available_at'); $table->unsignedInteger('created_at'); $table->index(['queue', 'reserved_at']); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('jobs'); } }

Next, let's run the migrate command so that it actually creates the jobs table in a database.

php artisan migrate

That's it as far as the jobs migration is concerned.

Next, let's create the Image model that will be used to manage images uploaded by the end user. The image model also requires an associated database table, so we'll use the --migrate option while creating the Image model.

php artisan make:model Image --migration

The above command should create the Image model class and an associated database migration as well.

The Image model class should look like this:

<?php // app/Image.php namespace App; use Illuminate\Database\Eloquent\Model; class Image extends Model { // }

And the database migration file should be created at database/migrations/YYYY_MM_DD_HHMMSS_create_images_table.php. We also want to store the original path of the image uploaded by the end user. Let's revise the code of the Image database migration file to look like the following.

<?php // database/migrations/YYYY_MM_DD_HHMMSS_create_images_table.php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateImagesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('images', function (Blueprint $table) { $table->increments('id'); $table->timestamps(); $table->string('org_path'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('images'); } }

As you can see, we've added the $table->string('org_path') column to store the path of the original image. Next, you just need to run the migrate command to actually create that table in the database.

$php artisan migrate

And that's it as far as the Image model is concerned.

Next, let's create an actual queue job that's responsible for processing image thumbnails. For the thumbnail processing, we're going to use a very popular image processing library—Intervention Image.

To install the Intervention Image library, go ahead and run the following command at the root of your application.

$php composer.phar require intervention/image

Now, it's time to create the Job class, and we'll use an artisan command to do that.

$php artisan make:job ProcessImageThumbnails

That should create the Job class template at app/Jobs/ProcessImageThumbnails.php. Let's replace the contents of that file with the following.

<?php // app/Jobs/ProcessImageThumbnails.php namespace App\Jobs; use App\Image as ImageModel; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Support\Facades\DB; class ProcessImageThumbnails implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $image; /** * Create a new job instance. * * @return void */ public function __construct(ImageModel $image) { $this->image = $image; } /** * Execute the job. * * @return void */ public function handle() { // access the model in the queue for processing $image = $this->image; $full_image_path = public_path($image->org_path); $resized_image_path = public_path('thumbs' . DIRECTORY_SEPARATOR . $image->org_path); // create image thumbs from the original image $img = \Image::make($full_image_path)->resize(300, 200); $img->save($resized_image_path); } }

When the queue worker starts processing any job, it looks for the handle method. So it's the handle method that holds the main logic of your job.

In our case, we need to create a thumbnail of an image uploaded by the user. The code of the handle method is pretty straightforward—we retrieve an image from the ImageModel model and create a thumbnail using the Intervention Image library. Of course, we need to pass the corresponding Image model when we dispatch our job, and we'll see it in a moment.

To test our newly created job, we'll create a simple upload form that allows the user to upload an image. Of course, we won't create image thumbnails right away; we'll defer that task so that it could be processed by the queue worker.

Let's create a controller file at app/Http/Controllers/ImageController.php as shown below.

<?php namespace App\Http\Controllers; use App\Image; use App\Jobs\ProcessImageThumbnails; use Illuminate\Http\Request; use Illuminate\Support\Facades\Redirect; use App\Http\Controllers\Controller; use Validator; class ImageController extends Controller { /** * Show Upload Form * * @param Request $request * @return Response */ public function index(Request $request) { return view('upload_form'); } /** * Upload Image * * @param Request $request * @return Response */ public function upload(Request $request) { // upload image $this->validate($request, [ 'demo_image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048', ]); $image = $request->file('demo_image'); $input['demo_image'] = time().'.'.$image->getClientOriginalExtension(); $destinationPath = public_path('/images'); $image->move($destinationPath, $input['demo_image']); // make db entry of that image $image = new Image; $image->org_path = 'images' . DIRECTORY_SEPARATOR . $input['demo_image']; $image->save(); // defer the processing of the image thumbnails ProcessImageThumbnails::dispatch($image); return Redirect::to('image/index')->with('message', 'Image uploaded successfully!'); } }

Let's create an associated view file at resources/views/upload_form.blade.php.

<!DOCTYPE html> <html lang="{{ config('app.locale') }}"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}" /> <title>Laravel</title> <!-- Fonts --> <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css"> <!-- Styles --> <style> html, body { background-color: #fff; color: #636b6f; font-family: 'Raleway', sans-serif; font-weight: 100; height: 100vh; margin: 0; } .full-height { height: 100vh; } .flex-center { align-items: center; display: flex; justify-content: center; } .position-ref { position: relative; } .top-right { position: absolute; right: 10px; top: 18px; } .content { text-align: center; } .title { font-size: 84px; } .links > a { color: #636b6f; padding: 0 25px; font-size: 12px; font-weight: 600; letter-spacing: .1rem; text-decoration: none; text-transform: uppercase; } .m-b-md { margin-bottom: 30px; } .alert { color: red; font-weight: bold; margin: 10px; } .success { color: blue; font-weight: bold; margin: 10px; } </style> </head> <body> <div class="flex-center position-ref full-height"> @if (Route::has('login')) <div class="top-right links"> @if (Auth::check()) <a href="{{ url('/home') }}">Home</a> @else <a href="{{ url('/login') }}">Login</a> <a href="{{ url('/register') }}">Register</a> @endif </div> @endif <div class="content"> <div class="m-b-md"> <h1 class="title">Demo Upload Form</h1> @if ($errors->any()) <div class="alert alert-danger"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif @if (session('message')) <div class="success"> {{ session('message') }} </div> @endif <form method="post" action="{{ url('/image/upload') }}" enctype="multipart/form-data"> <div> <input type="file" name="demo_image" /> </div> <br/> <div> <input type="hidden" name="_token" value="{{ csrf_token() }}"> <input type="submit" value="Upload Image"/> </div> </form> </div> </div> </div> </body> </html>

Finally, let's add routes for the index and upload actions in the routes/web.php file.

Route::get('image/index', 'ImageController@index'); Route::post('image/upload', 'ImageController@upload');

In the ImageController controller, the index method is used to render an upload form.

public function index(Request $request) { return view('upload_form'); }

When the user submits a form, the upload method is invoked.

public function upload(Request $request) { // upload image $this->validate($request, [ 'demo_image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048', ]); $image = $request->file('demo_image'); $input['demo_image'] = time().'.'.$image->getClientOriginalExtension(); $destinationPath = public_path('/images'); $image->move($destinationPath, $input['demo_image']); // make db entry of that image $image = new Image; $image->org_path = 'images' . DIRECTORY_SEPARATOR . $input['demo_image']; $image->save(); // defer the processing of the image thumbnails ProcessImageThumbnails::dispatch($image); return Redirect::to('image/index')->with('message', 'Image uploaded successfully!'); }

At the beginning of the upload method, you'll notice the usual file upload code that moves the uploaded file to the public/images directory. Next, we insert a database record using the App/Image model.

Finally, we use the ProcessImageThumbnails job to defer the thumbnail processing task. It's important to note that it's the dispatch method that's used to defer a task. At the end, the user is redirected to the upload page with a success message.

At this point in time, the job is added to the jobs table for processing. Let's confirm it by issuing the following query.

mysql> select * FROM lvl_jobs; | 1 | default | {"displayName":"App\\Jobs\\ProcessImageThumbnails","job":"Illuminate\\Queue\\CallQueuedHandler@call","maxTries":null,"timeout":null,"data":{"commandName":"App\\Jobs\\ProcessImageThumbnails","command":"O:31:\"App\\Jobs\\ProcessImageThumbnails\":5:{s:8:\"\u0000*\u0000image\";O:45:\"Illuminate\\Contracts\\Database\\ModelIdentifier\":2:{s:5:\"class\";s:9:\"App\\Image\";s:2:\"id\";i:2;}s:6:\"\u0000*\u0000job\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:5:\"delay\";N;}"}} | 0 | NULL | 1510219099 | 1510219099 |

You must be wondering, what does it take to process a job then? Don't worry—that's what we're going to discuss in the very next section.

Queue Worker

The job of the Laravel queue worker is to process jobs that are queued up for processing. In fact, there's an artisan command that helps us to start the queue worker process.

$php artisan queue:work

As soon as you run that command, it processes pending jobs. In our case, it should process the ProcessImageThumbnails job that was queued up when the user uploaded an image earlier.

$php artisan queue:work [YYYY-MM-DD HHMMSS] Processing: App\Jobs\ProcessImageThumbnails [YYYY-MM-DD HHMMSS] Processed: App\Jobs\ProcessImageThumbnails

You would have noticed that when you start a queue worker, it keeps running until you kill it manually or close the terminal. In fact, it's waiting for the next job to be processed. As soon as there's a new job in the queue, it'll be processed right away if the queue worker is running.

Of course, we can't keep it running that way, so we need to find a way for the queue worker to run permanently in the background.

To our rescue, there are several process management tools out there you could choose from. To name a few, here's a list:

  • Circus
  • daemontools
  • Monit
  • Supervisor
  • Upstart

You should choose a tool that you're comfortable with to manage the Laravel queue worker. Basically, we want to make sure that the queue worker should run indefinitely so that it processes queued jobs right away.

So that's the Queue API at your disposal. You can use it in your day-to-day development to defer time-consuming tasks for the betterment of the end user experience.

Conclusion

In this article, we discussed the Queue API in Laravel, which is really helpful should you wish to defer processing of resource-consuming tasks.

We started with a basic introduction to the Queue API, which involved a discussion of connections, queues, and jobs. In the second half of the article, we created a custom queue job that demonstrated how you could use the Queue API in the real world.

For those of you who are either just getting started with Laravel or looking to expand your knowledge, site, or application with extensions, we have a variety of things you can study in Envato Market.

Feel free to use the feedback form below to post your queries and suggestions.

Categories: Web Design

Introduction to Forms in Angular 4: Template-Driven Forms

Mon, 12/18/2017 - 04:00
What You'll Be Creating

Forms are critical to any modern front-end application, and they're a feature that we use every day, even if don't realize it. Forms are required for securely logging in a user to the app, searching for all the available hotels in a particular city, booking a cab, building a to-do list, and doing tons of other things that we are used to. Some forms have just a couple of input fields, whereas other forms could have an array of fields that stretch to a couple of pages or tabs. 

In this tutorial, we will be talking about different strategies available for developing forms in Angular. Irrespective of the strategy that you choose, here are the things that a form library should cover:

  • Support two-way binding so that the input control values are in sync with the component state.
  • Keep track of the form state and use visual cues to let the user know whether the current state is valid or not. For instance, if the username has invalid characters, a red border should appear around the input field for the username.
  • Have a mechanism to display validation errors properly.
  • Enable or disable certain parts of the form unless some validation criteria are met.
Introduction to Forms in Angular

Angular, being a full-fledged front-end framework, has its own set of libraries for building complex forms. The latest version of Angular has two powerful form-building strategies. They are:

  • template-driven forms 
  • model-driven or reactive forms

Both the technologies belong to the @angular/forms library and are based on the same form control classes. However, they differ remarkably in their philosophy, programming style, and technique. Choosing one over the other depends on your personal taste and also on the complexity of the form that you are trying to create. In my opinion, you should try both the approaches first and then choose one that fits your style and the project at hand. 

The first part of the tutorial will cover template-driven forms with a practical example: building a signup form with validation for all form fields. In the second part of this tutorial, we will retrace the steps to create the same form using a model-driven approach instead. 

Template-Driven Forms

The template-driven approach is a strategy that was borrowed from the AngularJS era. In my opinion, it is the most straightforward method for building forms. How does it work? We will be using some Angular directives. 

Directives allow you to attach behavior to elements in the DOM.
— Angular Documentation

Angular provides form-specific directives that you can use to bind the form input data and the model. The form-specific directives add extra functionality and behavior to a plain HTML form. The end result is that the template takes care of binding values with the model and form validation. 

In this tutorial, we will be using template-driven forms to create the signup page of an application. The form will cover the most common form elements and different validation checks on these form elements. Here are the steps that you will follow in this tutorial.

  • Add FormsModule to app.module.ts.
  • Create a class for the User model.
  • Create initial components and layout for the signup form.
  • Use Angular form directives like ngModel, ngModelGroup, and ngForm.
  • Add validation using built-in validators.
  • Display validation errors meaningfully.
  • Handle form submission using ngSubmit.

Let's get started.

Prerequisites

The code for this project is available on my GitHub repo. Download the zip or clone the repo to see it in action. If you prefer to start from scratch instead, make sure that you have Angular CLI installed. Use the ng command to generate a new project. 

$ ng new SignupFormProject

Next, generate a new component for the SignupForm.

ng generate component SignupForm

Replace the contents of app.component.html with this:

<app-signup-form> </app-signup-form>

Here is the directory structure for the src/ directory. I've removed some non-essential files to keep things simple.

. ├── app │   ├── app.component.css │   ├── app.component.html │   ├── app.component.ts │   ├── app.module.ts │   ├── signup-form │   │   ├── signup-form.component.css │   │   ├── signup-form.component.html │   │   └── signup-form.component.ts │   └── User.ts ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css ├── tsconfig.app.json └── typings.d.ts

As you can see, a directory for the SignupForm component has been created automatically. That's where most of our code will go. I've also created a new User.ts for storing our User model.

The HTML Template

Before we dive into the actual component template, we need to have an abstract idea of what we are building. So here is the form structure that I have in my mind. The signup form will have several input fields, a select element, and a checkbox element. 


Here is the HTML template that we will be using for our registration page. 

HTML Template <div class="row custom-row"> <div class= "col-sm-5 custom-container jumbotron"> <form class="form-horizontal"> <fieldset> <legend>SignUp</legend> <!--- Email Block ---> <div class="form-group"> <label for="inputEmail">Email</label> <input type="text" id="inputEmail" placeholder="Email"> </div> <!--- Password Block ---> <div class="form-group"> <label for="inputPassword">Password</label> <input type="password" id="inputPassword" placeholder="Password"> </div> <div class="form-group"> <label for="confirmPassword" >Confirm Password</label> <input type="password" id="confirmPassword" placeholder="Password"> </div> <!--- Select gender Block ---> <div class="form-group"> <label for="select">Gender</label> <select id="select"> <option>Male</option> <option>Female</option> <option>Other</option> </select> </div> <!--- Terms and conditions Block ---> <div class="form-group checkbox"> <label> <input type="checkbox"> Confirm that you've read the Terms and Conditions </label> </div> <!--- Buttons Block ---> <div class="form-group"> <button type="reset" class="btn btn-default">Cancel</button> <button type="submit" class="btn btn-primary">Submit</button> </div> </fieldset> </form> </div> </div>

The CSS classes used in the HTML template are part of the Bootstrap library used for making things pretty. Since this is a not a design tutorial, I won't be talking much about the CSS aspects of the form unless necessary. 

Basic Form Setup

To use the template-driven form directives, we need to import the FormsModule from @angular/forms and add it to the imports array in app.module.ts.

app/app.module.tsimport { FormsModule } from '@angular/forms'; @NgModule({ . . imports: [ BrowserModule, FormsModule ], . . }) export class AppModule { }

Next, create a class that will hold all properties of the User entity. We can either use an interface and implement it in the component or use a TypeScript class for the model.

app/User.tsexport class User { id: number; email: string; //Both the passwords are in a single object password: { pwd: string; confirmPwd: string; }; gender: string; terms: boolean; constructor(values: Object = {}) { //Constructor initialization Object.assign(this, values); } }

Now, create an instance of the class in the SignupForm component. I've also declared an additional property for the gender. 

app/signup-form/signup-form.component.tsimport { Component, OnInit } from '@angular/core'; // Import the User model import { User } from './../User'; @Component({ selector: 'app-signup-form', templateUrl: './signup-form.component.html', styleUrls: ['./signup-form.component.css'] }) export class SignupFormComponent implements OnInit { //Property for the gender private gender: string[]; //Property for the user private user:User; ngOnInit() { this.gender = ['Male', 'Female', 'Others']; //Create a new user object this.user = new User({ email:"", password: { pwd: "" , confirm_pwd: ""}, gender: this.gender[0], terms: false}); } }

For the signup-form.component.html file, I am going to use the same HTML template discussed above, but with minor changes. The signup form has a select field with a list of options. Although that works, we will do it the Angular way by looping through the list using the ngFor directive.

app/signup-form/signup-form.component.html<div class="row custom-row"> <div class= "col-sm-5 custom-container jumbotron"> <form class="form-horizontal"> <fieldset> <legend>SignUp</legend> . . <!--- Gender Block --> <div class="form-group"> <label for="select">Gender</label> <select id="select"> <option *ngFor = "let g of gender" [value] = "g"> {{g}} </option> </select> </div> . . </fieldset> </form> </div> </div>

Next, we want to bind the form data to the user class object so that when you enter the signup data into the form, a new User object is created that temporarily stores that data. This way, you can keep the view in sync with the model, and this is called binding. 

There are a couple of ways to make this happen. Let me first introduce you to ngModel and ngForm.

ngForm and ngModel

ngForm and ngModel are Angular directives that are essential to creating template-driven forms. Let's start with ngForm first. Here is an excerpt about ngForm from the Angular docs.

The NgForm directive supplements the form element with additional features. It holds the controls you created for the elements with an ngModel directive and name attribute, and monitors their properties, including their validity. It also has its own valid property which is true only if every contained control is valid.

First, update the form with the ngForm directive:

app/signup-form/signup-form.component.html<form class="form-horizontal" #signupForm = "ngForm"> . . </form>

#signupForm is a template reference variable that refers to the ngForm directive which governs the entire form. The example below demonstrates the use of a ngForm reference object for validation.

app/signup-form/signup-form.component.html<button type="submit" class="btn btn-success" [disabled]="!signupForm.form.valid"> Submit </button>

Here, signupForm.form.valid will return false unless all the form elements pass their respective validation checks. The submit button will be disabled until the form is valid.  

As for binding the template and the model, there are plenty of ways to do this, and ngModel has three different syntaxes to tackle this situation. They are:

  1. [(ngModel)] 
  2. [ngModel]
  3. ngModel

Let's start with the first one.

Two-Way Binding Using [(ngModel)]

[(ngModel)] performs two-way binding for reading and writing input control values. If a [(ngModel)] directive is used, the input field takes an initial value from the bound component class and updates it back whenever any change to the input control value is detected (on keystroke and button press). The image below describes the two-way binding process better.

Here is the code for the email input field:

<div class="form-group"> <label for="inputEmail">Email</label> <input type="text" [(ngModel)] = "user.email" id="inputEmail" name="email" placeholder="Email"> </div>

[(ngModel)] = "user.email" binds the user's email property to the input value. I've also added a name attribute and set name="email". This is important, and you will get an error if you've not declared a name attribute while using ngModel. 

Similarly, add a [(ngModel)] and a unique name attribute to each form element. Your form should look something like this now:

app/signup-form/signup-form.component.html. . . <div ngModelGroup="password"> <div class="form-group" > <label for="inputPassword">Password</label> <input type="password" [(ngModel)] = "user.password.pwd" name="pwd" placeholder="Password"> </div> <div class="form-group"> <label for="confirmPassword" >Confirm Password</label> <input type="password" [(ngModel)] = "user.password.confirmPwd" name="confirmPwd" placeholder="Confirm Password"> </div> </div> <div class="form-group"> <label for="select">Gender</label> <select id="select" [(ngModel)] = "user.gender" name = "gender"> <option *ngFor = "let g of gender" [value] = "g"> {{g}} </option> </select> </div> . . .

The ngModelGroup is used to group together similar form fields so that we can run validations only on those form fields. Since both the password fields are related, we will put them under a single ngModelGroup. If everything is working as expected, the component-bound user property should be in charge of storing all the form control values. To see this in action, add the following after the form tag:

{{user | json}}

Pipe the user property through the JsonPipe to render the model as JSON in the browser. This is helpful for debugging and logging. You should see a JSON output like this. 

The values are flowing in from the view to the model. What about the other way around? Try initializing the user object with some values.

app/signup-form/signup-form.component.tsthis.user = new User({ //initialized with some data email:"thisisfromthemodel@example.com", password: { pwd: "" , confirm_pwd: ""}, gender: this.gender[0] });

And they automatically appear in the view:

{ "email": "thisisfromthemodel@example.com", "password": { "pwd": "", "confirm_pwd": "" }, "gender": "Male" }

The two-way binding [(ngModel)] syntax helps you build forms effortlessly. However, it has certain drawbacks; hence, there is an alternate approach that uses ngModel or [ngModel].

Adding ngModel to the Mix

When ngModel is used, we are in fact responsible for updating the component property with the input control values and vice versa. The input data doesn't automatically flow into the component's user property.

So replace all instances of [(ngModel)] = " " with ngModel. We will keep the name attribute because all three versions of ngModel need the name attribute to work. 

app/signup-form/signup-form.component.html<div class="form-group"> <label for="inputEmail">Email</label> <input type="text" ngModel id="inputEmail" name="email" placeholder="Email"> </div>

With ngModel, the value of the name attribute will become a key of the ngForm reference object signupForm that we created earlier. So, for example, signupForm.value.email will store the control value for the email id. 

Replace {{user | json}} with {{signupForm.value | json }} because that's where all the state is stored right now. 

One-Way Binding Using [ngModel]

What if you need to set the initial state from the bound class component? That's what the [ngModel] does for you. 

Here the data flows from the model to the view. Make the following changes to the syntax to use one-way binding:

app/signup-form/signup-form.component.html<div class="form-group"> <label for="inputEmail">Email</label> <input type="text" [ngModel] = "user.email" id="inputEmail" name="email" placeholder="Email"> </div>

So which approach should you choose? If you're using [(ngModel)] and ngForm together, you will eventually have two states to maintain—user and signupForm.value—and that could be potentially confusing. 

{ "email": "thisisfromthemodel@example.com", "password": { "pwd": "thisispassword", "confirm_pwd": "thisispassword" }, "gender": "Male" } //user.value { "email": "thisisfromthemodel@example.com", "password": { "pwd": "thisispassword", "confirm_pwd": "thisispassword" }, "gender": "Male" } //signupForm.value

Hence, I will recommend using the one-way binding method instead. But that's something for you to decide.

Validation and Displaying Error Messages 

Here are our requirements for the validation.

  • All form controls are required.
  • Disable the submit button until all input fields are filled.
  • The email field should strictly contain an email id.
  • The password field should have a minimum length of 8.
  • Both the password and confirmation should match.
Our form with validation in place

The first one is easy. You have to add a required validation attribute to each form element like this:

app/signup-form/signup-form.component.html<input type="text" [ngModel] = "user.email" name="email" #email = "ngModel" placeholder="Email" required>

Apart from the required attribute, I've also exported a new #email template reference variable. This is so that you can access the input box's Angular control from within the template itself. We will use it to display errors and warnings. Now use the button's disabled property to disable the button:

app/signup-form/signup-form.component.html<button type="submit" class="btn btn-success" [disabled]="!signupForm.form.valid"> Submit </button>

To add a constraint on email, use the pattern attribute that works with input fields. Patterns are used to specify regular expressions like the one below:

pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$"

For the password field, all you have to do is add a minlength=" " attribute:

app/signup-form/signup-form.component.html <input type="password" ngModel id="inputPassword" name="pwd" #pwd = "ngModel" placeholder="Password" minlength="8" required>

To display the errors, I am going to use the conditional directive ngIf on a div element. Let's start with the input control field for email:

app/signup-form/signup-form.component.html<div class="form-group"> <label for="inputEmail">Email</label> <input type="text" [ngModel] = "user.email" name="email" #email = "ngModel" id="inputEmail" placeholder="Email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" required> </div> <!-- This is the error section --> <div *ngIf="email.invalid && (email.dirty || email.touched)" class="alert alert-danger"> <div *ngIf = "email.errors?.required"> Email field can't be blank </div> <div *ngIf = "email.errors?.pattern && email.touched"> The email id doesn't seem right </div> </div>

There is a lot going on here. Let's start with the first line of the error section.

<div *ngIf="email.invalid && (email.dirty || email.touched)" class="alert alert-danger">

Remember the #email variable that we exported earlier? It carries some amount of information about the input control state of the email field. This includes: email.valid, email.invalid, email.dirty, email.pristine, email.touched, email.untouched, and email.errors.  The image below describes each of those properties in detail.

So the div element with the *ngIf will be rendered only if the email is invalid. However, the user will be greeted with errors about the input fields being blank even before they have a chance to edit the form. 

To avoid this scenario, we've added the second condition. The error will be displayed only after the control has been visited or the control's value has been changed.

The nested div elements are used to cover all the cases of validation errors. We use email.errors to check all possible validation errors and then display them back to the user in the form of custom messages. Now, follow the same procedure for the other form elements. Here is how I've coded the validation for the passwords. 

app/signup-form/signup-form.component.html <div ngModelGroup="password" #userPassword="ngModelGroup" required > <div class="form-group"> <label for="inputPassword">Password</label> <input type="password" ngModel name="pwd" id="inputPassword" placeholder="Password" minlength ="8" required> </div> <div class="form-group"> <label for="confirmPassword" >Confirm Password</label> <input type="password" ngModel name="confirmPwd" id="confirmPassword" placeholder="Confirm Password"> </div> <div *ngIf="(userPassword.invalid|| userPassword.value?.pwd != userPassword.value?.confirmPwd) && (userPassword.touched)" class="alert alert-danger"> <div *ngIf = "userPassword.invalid; else nomatch"> Password needs to be more than 8 characters </div> <ng-template #nomatch > Passwords don't match </ng-template> </div> </div>

This is starting to look a bit messy. Angular has a limited set of validator attributes: required, minlength, maxlength, and pattern. To cover any other scenario like that of password comparison, you will have to rely on nested ngIf conditionals as I did above. Or ideally, create a custom validator function, which I will cover in the third part of this series.

In the code above, I've used the ngIf else syntax which was introduced in the latest version of Angular. Here is how it works:

<div *ngIf="isValid;else notvalid"> Valid content... </div> <ng-template #notValid>Not valid content...</ng-template>Submit the Form Using ngSubmit

We have nearly finished the form. Now we need to be able to submit the form, and the control of the form data should be handed over to a component method, say onFormSubmit().

app/signup-form/signup-form.component.ts<form novalidate (ngSubmit)="onFormSubmit(signupForm)" #signupForm="ngForm"> ...

Now, for the component:

app/signup-form/signup-form.component.ts... public onFormSubmit({ value, valid}: { value: User, valid: boolean }) { this.user = value; console.log( this.user); console.log("valid: " + valid); } ...Final Demo

Here is the final version of the application. I've added a few bootstrap classes to make the form pretty.

Summary

We're all done here. In this tutorial, we covered everything that you need to know about creating a form in Angular using the template-driven approach. Template-driven forms are popular for their simplicity and ease of use. 

However, if you need to build a form with lots of form elements, this approach will become messy. So, in the next tutorial, we will cover the model-driven way of building the same form. 

Share your thoughts in the comments below.

Categories: Web Design

Get Rid of Bugs Quickly Using BugReplay

Wed, 12/13/2017 - 04:00

As a web developer, you are bound to come across clients who are not very tech savvy. Some clients might want you to create a new website for them, while others might want to only make changes to specific sections or add new functionality. This is how the situation generally plays out:

  1. You update a section of the website, check that everything is working fine, and then go to bed.
  2. Next day, you wake up only to find an email or message from your client which says that the website is not working as expected.
  3. You start wondering what it is that's not working and open the website on your own device. At this point, you may be able to reproduce the issue the client is talking about and fix it. However, in some unfortunate cases, the website would seem to be working correctly, and you won't be able to see what the client is complaining about.
  4. This is when the trouble begins. The website may not be working for your client as well as many other people, but you have no idea what's wrong and how to resolve the issue.
  5. You start asking the client what's not working, the browser they are using, exactly what they were doing, etc., in the hope of being able to reproduce the issue on your end. Sometimes you can reproduce the issue, but sometimes you can't.

The whole process is very frustrating for both you and your clients. In situations like these, I wish that I could just sit right next to the client and see everything myself. 

BugReplay helps you do something very similar. You no longer have to ask your users tons of questions about their browsers, cookies, plugins, etc. All you have to do is give them a link that they can click on to start browser recording.

You can use BugReplay for internal testing as well. In this article, we will go over all the features of this software that can make the internal testing of a website or providing awesome customer support a breeze.

BugReplay Records Everything Visible in the Browser Tab

Whenever you ask your users the steps they followed in order to reproduce a bug, you can never be sure that the users have not missed any steps. BugReplay helps you overcome this very common problem by recording everything the users did while trying to reproduce the bug. This is not only helpful when resolving customer complaints, but it also speeds up internal testing and makes the whole process very efficient.

As you can see in this video, BugReplay records every action the user takes, from button clicks to scrolling up and down the browser window.

While seeing what the user did when they ran into trouble with your website is helpful, it is still hard to know if any plugin installed by the user interfered with a script or if the user has disabled cookies, etc. Just by watching the above video, you may conclude that the images are not showing up because the call to retrieve the images failed. 

It is also possible that the images were retrieved without any error, but they were not displayed because of some issue with the code that was supposed to arrange them in two different columns.

All you can do at this point is just guess and wish there was a way for you to see all the network calls as well as the JS console to determine what went wrong. Luckily, BugReplay also records all the network requests and responses. 

These calls are all synchronized with the screen recording to help you figure out exactly when a network call was fired. The calls can be filtered based on a variety of factors like the domain, MIME type and HTTP status of the request, etc. The following video shows you how BugReplay can help you in quickly figuring out if any of the network calls caused the bug.

In the video, try to observe how clicking on the Settings icon on the right and applying different filters changes the list of requests shown in the Network Traffic Tab. Only the highlighted filters are applied at any given time. You should also see that the Network Traffic tab doesn't show any calls at the beginning. This is because a call is added to the tab only after a request has been made. Knowing when a call was fired goes a long way in figuring out what went wrong with the app or website.

The filters can prove very helpful when you are dealing with websites that can make a large number of requests with varying HTTP status codes and MIME types. In the following image, I have shown the result of filtering the requests by domain and selected localhost. As you can see, our network call was fired as expected.

You can also click on any network call to find out more about it, like the duration of the request. You can also check the request and response headers. 

The following screenshot shows the details of our second request. As you can see, we are getting the JSON response back. This means that something must have been wrong with the code that was supposed to place the images in two different columns.


Just like filtering network requests, you can also filter all the console messages under the JavaScript Logs tab based on their domain, level, or source. In this case, we are looking for an error message, and that's why we set the level filter to error. Once you click on the error that you want to inspect, you will see more details about it. Here is a screenshot of the error which was preventing the images from displaying in our case.

Thanks to BugReplay, we now know the library as well as the exact function which prevented our images from displaying. You can see how easy the software makes it for developers to debug their websites.

Internal Testing and Customer Support

It doesn't matter if you are using BugReplay for internal testing or customer support. The software records all the network calls and console logs in the same manner. However, keep in mind that you (or your users) need to use different browser extensions for these purposes, and the process is slightly different as well.

Here are the steps to follow when using BugReplay for internal testing:

  1. The first thing that you need to do is register and create an account. You can use the software for free for the first 30 days. 
  2. In the next step, you can download the BugReplay extension for Chrome. If you primarily use Firefox for your work, you can download the BugReplay Firefox extension instead.
  3. Once you have installed the extension, you can just click on the Start Recording button inside it to record a bug. 
  4. BugReplay also allows you to replay the video before saving it in order to make sure that the video captures all the necessary details properly. You can give each recording an optional title and description in order to identify it later.

Instead of recording a video, you can also take one or multiple screenshots in order to point out a bug in the website.

If your users want to report a bug in your website, they will have to download another extension called Feedback by BugReplay. First, you will have to generate a link from which the users can download the extension. The link can be generated by clicking on the Request Feedback Report tab in your account. 

You can give the link a title and an expiration date as well. After successful installation, the extension gives the users some easy-to-follow instructions so that they can record the bug with ease. The users can also optionally provide a title and description for the bug along with an email address for any further communications.

Since BugReplay records everything from the steps taken by a user to the network calls and the console logs, it becomes a lot easier for your users to submit detailed bug reports without getting frustrated with tons of questions. I would also like to point out that the Feedback by BugReplay extension doesn't give the users access to any of your other videos or to the dashboard. 

More BugReplay Features and Integrations

If you decide to use BugReplay for internal testing, you will probably be working with a team. Everyone in a team can access each other's reports, making it easy for them to work together in order to resolve bugs. You can invite other people to join your team by clicking on your name in the upper right corner of your BugReplay account page and then entering the names and email addresses of people that you want to invite.

Sometimes, you might want to share a bug report with people who are not in your team. BugReplay allows you to create a shareable URL for each of your videos and then make the video accessible to anyone with a link. You can share a video by clicking the share link next to that video in your dashboard. Once the concerned people have watched the video, you can revoke the shared URL by clicking on Unshare.

If you and your team use either GitHub or Jira, it makes sense to allow you to file issues with both of them directly using BugReplay. The BugReplay team has already written a detailed article that outlines all the necessary instructions to integrate JIRA

Integrating BugReplay with GitHub is easy as well. All you have to do is click on Notifications and Integrations on your account page and then select GitHub Issue Tracker under Add Integration. Similarly, you can integrate BugReplay with Slack by following the on-screen instructions.

If you want to receive an email whenever your users submit a bug report, you can provide BugReplay with one or more email addresses through which you want to be notified.

All these features of BugReplay make it one of the best tools to internally test your website and create detailed reports that are accessible to everyone on the team. Here is a testimonial from one of the many happy users of BugReplay.

BugReplay has greatly reduced my team's need to type tedious Steps to Reproduce and nearly eliminated uncertainty in bug reports - our dev team can start troubleshooting right away using BugReplay.
— Matt Viirlee, Project ManagerFinal Thoughts

BugReplay makes it very easy for you to provide awesome customer support to your customers and significantly speed up internal testing by providing some useful tools. Any bug report created by either your users or a member of the team will be visible to the whole team now. The ability to see all the network calls and the console log will give you the most detailed bug reports possible, without bothering your client with a single question about the bug.

If you have been looking for a tool that can help your users or team create detailed bug reports, BugReplay is probably going to satisfy all your needs. Since you can register for a BugReplay account without paying anything for the first 30 days, I would suggest that you give it a try. If things work out well, you will have an amazing tool that keeps both your clients and internal testing teams happy.

Categories: Web Design

Manipulating HTML5 Canvas Using Konva: Part 1, Getting Started

Mon, 12/11/2017 - 05:00

The HTML5 canvas has been supported by all popular browsers for a long time now. You can use it for drawing graphics in a browser with the help of JavaScript. The graphics that can be created on a canvas range from simple lines and shapes to photo compositions and animations.

In this series, you will learn about a very helpful canvas library called Konva. You can use Konva to draw different shapes on the canvas or the stage. Among other things, the library allows you to scale, rotate and animate all these shapes and attach event listeners to them. 

This tutorial will focus on the fundamental concepts of the library while providing a brief overview of different features of the library. After that, we will move on to more specific and complex topics later. The library first came into existence as a fork of the popular KineticJS library. 

Stage, Layers, and Shapes

Everything that you draw with Konva will require you to create a stage using Konva.Stage. You can specify the container element of a stage using the container attribute. Each stage also requires a width and height value which can be specified using the width and height attributes respectively.

A single stage can contain multiple layers. Each of these layers will have two <canvas> renderers. The scene renderer is used to draw all the shapes that are visible to you on the stage. The hit graph renderer is hidden from the users. It is used to perform high-performance event detection.

A single layer can contain multiple shapes, groups of different shapes, or a group of groups. The stage, layers, groups and shapes act like virtual nodes which can be individually styled and transformed.

Drawing Shapes Using Konva

Before we create any shapes, we need to include the library in your project. There are multiple ways of doing this. If you are using package managers, you can run the following commands.

npm install konva // OR bower install konva

You can also link directly to a minified version of the library hosted on cdnjs and jsDelivr.

Once you have installed the library, you can use the following code to create rectangular shapes on the canvas.

var canvasWidth = 600; var canvasHeight = 400; var stage = new Konva.Stage({ container: "example", width: canvasWidth, height: canvasHeight }); var layerA = new Konva.Layer(); var rectA = new Konva.Rect({ x: 75, y: 150, width: 200, height: 50, rotation: 45, fill: "blue", stroke: "black", strokeWidth: 4 }); var rectB = new Konva.Rect({ x: 350, y: 50, width: 100, height: 250, cornerRadius: 50, fill: "red", stroke: "brown", strokeWidth: 10 }); layerA.add(rectA); layerA.add(rectB); stage.add(layerA);

Drawing anything on the canvas is a five-step process. First, you need to instantiate a stage where different shapes would be drawn using Konva.Stage. This requires you to specify the width and height of the stage as well as the id for the container element which would contain the stage. In our case, the rectangles are being drawn inside a div whose id is example.

In the next step, you have to instantiate all the layers that you want to render on your stage. We are only creating a single layer in this example, but you can create multiple layers and add them all to a single stage. Different layers can be very useful when your background consists of static as well as moving elements. In such cases, you can add the static elements on one layer and moving elements on the other. Since you won't have to update the static background after each redraw, this can drastically improve the performance.

After creating the layers, you can initialize different shapes like rectangles, ellipses, stars and rings that you want to show on the layers. Finally, you have to add the shapes to the layers and the layers to the stage.

Creating Groups in Konva

Grouping different shapes together is a good idea when you want to manage all the shapes as a single unit. For example, let's say that you have created a car using two circles for wheels and two rectangular blocks for the body. If you want to move this car ahead without creating a group, you will have to individually translate all the shapes one at a time. A more efficient method is to just add the circles and the rectangles to a group and translate them all at once.

To add any shape to a group, you need to use the add() method, just like you did when adding shapes to a layer. You can also add a group to another group to create more complex entities. For example, you could create a person inside the car as one group and add that person to the group that represents the car.

In the following example, I have kept things simple and only created a carA group. After that, I can rotate and scale the whole car at once.

var canvasWidth = 600; var canvasHeight = 400; var stage = new Konva.Stage({ container: "example", width: canvasWidth, height: canvasHeight }); var layerA = new Konva.Layer(); var wheelA = new Konva.Ring({ x: 130, y: 230, innerRadius: 5, outerRadius: 30, fill: "gray", stroke: "black", name: "First Wheel" }); var wheelB = new Konva.Ring({ x: 270, y: 230, innerRadius: 5, outerRadius: 30, fill: "gray", stroke: "black", name: "Second Wheel" }); var frameA = new Konva.Rect({ x: 80, y: 150, width: 240, height: 60, cornerRadius: 10, fill: "red", stroke: "black", name: "Bottom Frame" }); var frameB = new Konva.Rect({ x: 135, y: 90, width: 120, height: 60, cornerRadius: 10, fill: "orange", stroke: "black", name: "Top Frame" }); var carA = new Konva.Group({ x: 50, y: 0, rotation: 20, scaleX: 1.2 }); carA.add(wheelA, wheelB, frameA, frameB); layerA.add(carA); stage.add(layerA);

Layering in Konva

You already know about layers in Konva. Layering is something different. By default, all shapes that you add to a layer are drawn in the order in which they were added. This means that shapes added to a layer after all others will be drawn on top of other shapes.

Konva allows you to control the order in which the shapes are drawn using different layering methods like moveToTop(), moveToBottom(), moveUp(), moveDown(), and zIndex().

The moveToTop() method will draw the given shape over all other shapes that have been added to the same layer. Shapes drawn on a layer that was added to the Konva stage after the layer of our specific shape will still remain above our shape. This is why the indigo circle in the following example remains below the light green circle even after calling moveToTop().

The moveToBottom() method will draw the given shape below all other shapes that have been added to the same layer. Just like moveToTop(), the shapes will move to the bottom of their own layers and not the layers below them.

The moveUp() and moveDown() methods move the shape on which they are called, one position above or below their current position in the same layer. The zIndex() method is used to set the index of a shape inside its parent layer. Unlike CSS, you cannot set an arbitrary zIndex value in Konva. For a layer with 10 shapes, the zIndex value can only be between 0 and 9 (inclusive).

In the above example, you can see that just pressing the "Indigo Top" button does not draw the indigo circle above all others, while pressing "Indigo Above all Others" will position it at the top. This is because the last button also moves the layer containing the indigo circle to the top.

Since the circles can be dragged around, it might be a good idea to drag them over each other and see how the position of the indigo circle changes when you press different buttons.

Final Thoughts

We have covered some fundamental concepts related to Konva in this tutorial. You should now be able to draw some common shapes on the canvas and move them around as a group. The tutorial also showed you how to push a particular shape up or down in case of an overlap.

JavaScript has become one of the de facto languages of working on the web. It’s not without its learning curves, and there are plenty of frameworks and libraries to keep you busy, as well. If you’re looking for additional resources to study or to use in your work, check out what we have available on Envato Market.

If you have any questions related to this tutorial, feel free to let me know in the comments. The next tutorial will teach you how to draw basic shapes in Konva.

Categories: Web Design

10 Must-See Easy Digital Downloads Extensions for Your WordPress Site

Fri, 12/08/2017 - 04:09

Selling products online has been a game-changer over the past several years. With the reasonable cost of an e-commerce platform, business owners, artists, musicians, and more have started their own online stores.

The power and flexibility of WordPress have been amazing and have led to the rise of the most popular e-commerce solution on the web—WooCommerce.

Because WooCommerce has a broader focus that includes physical goods and services, it has left room for a more efficient and niche solution for e-commerce businesses interested in exclusively selling digital downloads. And that solution is Easy Digital Downloads.

This flexible and easy-to-use free e-commerce platform focuses on digital downloads, providing many useful features that are essential to managing an online storefront. There are, however, many different ways to extend the platform. Let's take a look at 10 must-see Easy Digital Downloads extensions for your WordPress site from Envato Market:

1. Easy Digital Downloads - Points and Rewards

Transform your faithful customers into frequent customers with Easy Digital Downloads - Points and Rewards. Configure and tweak your points program for maximum sales with the many different options included within this Easy Digital Downloads extension for your WordPress site.

"Customers can build up their point balance over time and then choose exactly when they wish to redeem those points for a discount. Customer point balances can be manually adjusted at any time by store admins."

Some of the features include:

  • set maximum discounts based on category, cart, and product levels
  • log generated of all points changes made for customers
  • define point earnings and point values for set discounts
  • and more!

Easily start your customer rewards program with the Easy Digital Downloads - Points and Rewards plugin, today!

2. QuickBooks (Intuit) Gateway for Easy Digital Downloads

As a small business, you may already be using QuickBooks. And if you're already using QuickBooks, you may already have a QuickBooks (Intuit) Merchant Account. If this is your business or could be your business, you need to check out the QuickBooks (Intuit) Gateway for Easy Digital Downloads.

Simply put:

"QuickBooks (Intuit) Payment Gateway provides an easier, cost effective and simple alternative for a small business for accepting credit cards."

QuickBooks (Intuit) Gateway for Easy Digital Downloads. Check it out.

3. Easy Digital Downloads Email Templates

Every touch point you have with a customer is important, especially immediately after they've made a purchase. Set yourself apart from the competition with amazing transactional customer emails from the Easy Digital Downloads Email Templates extension.

"Fully customizable texts, colors & images for your unique store design."

This Easy Digital Downloads extension boasts:

  • responsive design for all screen sizes and mobile devices
  • 20 different styles of email templates
  • customize images, text, colors, fonts, etc.
  • and more!

Add a personal touch or keep your e-commerce storefront branding with every notification and email sent via Easy Digital Downloads.

Easy Digital Downloads Email Templates makes it easy to do, so you can focus on your business.

4. Easy Digital Downloads - Currency Converter

If you're selling something that can be digitally downloaded, then the entire world becomes your marketplace!

So what about other currencies? Easy Digital Downloads - Currency Converter has got you covered.

"Easy Digital Download Currency Converter uses Open Exchange Rates for converting your product prices to a currency of your customers choice!"

Packed with useful features, this is what your world-wide-web store needs:

  • automatically detect currency based on location
  • fully responsive for all screen sizes
  • option for product price appending
  • full localization support
  • and more!

The Easy Digital Downloads - Currency Converter extension takes the pain out of currency conversion.

5. Easy Digital Downloads Product Audio Sampler Player

If you're selling music downloads—or any audio download for that matter—then the Easy Digital Downloads Product Audio Sampler Player is the perfect addition to your Easy Digital Downloads storefront.

Easy to use, install, and configure, this extension lets you add an amazing feature to your e-commerce website.

"You simply upload a sample file in the backend and EDD Player will take care of the rest."

Features include:

  • single or playlist mode
  • 3 custom positions
  • clean design
  • and more

It's a feature that's easy to overlook, but impossible to live without.

The Easy Digital Downloads Product Audio Sampler Player is the perfect extension for music artists and musicians selling through Easy Digital Downloads.

6. Easy Digital Downloads - PDF Vouchers

This is a really great solution for both exclusively online businesses and those that cross over to brick and mortar. Easy Digital Downloads - PDF Vouchers makes it super easy to generate sales and gift vouchers for customers.

"This is perfect for stores that wish to sell tickets to events, discount codes for on-site pickup, class admission tickets and more."

Customers are given the ability to set a recipient name, email, and personal message for vouchers purchased through this Easy Digital Downloads extension for your WordPress site.

It's packed full of features:

  • create voucher templates with a drag-and-drop interface
  • PDF vouchers are fully customizable
  • unlimited or limited codes
  • import codes via CSV
  • and much more!

A great solution for online payments for any types of goods or services. This plugin has enough features to be very useful, without trapping itself into too tight of a niche.

Easy Digital Downloads - PDF Vouchers is one of the more impressive extensions for both local and online businesses.

7. Easy Digital Downloads Product Upsells

Boost your sales with upsells! Not only is it a profitable thing to do, but it can also be very helpful to your customers. Use Easy Digital Downloads Product Upsells to make upsells—easy!

"It will help you to display products you want as an upsell to your customers based on your selection."

Customize the look of product upsells and more:

  • easy to customize
  • easy to setup
  • easy to upsell

Easy Digital Downloads Product Upsells is a simple plugin with a low investment threshold. There's hardly any reason why you shouldn't try this plugin.

8. Easy Digital Downloads - Social Login

Signing up for a new account can be a real hassle. Customers may even add products to their cart, but get bogged down when they are faced with all the required fields to set up a new account.

The first purchase is always the hardest. Unless you're using the Easy Digital Downloads - Social Login plugin.

"...Allows users to log in and checkout with social networks such as Facebook, Twitter, Google, Yahoo, LinkedIn, Foursquare, Windows Live, VK.com, Instagram, Amazon and Paypal."

Features also included:

  • shortcode support to place login wherever you like
  • sends new account details to user email
  • custom URL redirect after social login
  • and much, much more!

The most important feature? One-click registration.

It's never been easier to sign up new customers than with the Easy Digital Downloads - Social Login. You're welcome.

9. Easy Digital Downloads - Dropbox

There are several reasons why it works well to host your e-commerce download files on Dropbox, and Easy Digital Downloads - Dropbox makes it super easy to integrate Dropbox into Easy Digital Downloads.

"Easily choose a file from your Dropbox account via the Choose from Dropbox button and the plugin will do the rest."

This plugin:

  • lets you select and upload files into your Dropbox account from the WordPress Admin
  • is easy to customize, set up, and use
  • is translation ready
  • and more!

Adding Dropbox to Easy Digital Downloads has never been this easy. Easy Digital Downloads - Dropbox is a no-brainer.

10. Fancy Popup - Popup Plugin For WordPress

Fancy Popup - Popup Plugin For WordPress is not specifically built for Easy Digital Downloads—but it is compatible and extremely useful for e-commerce WordPress websites.

"...Design amazing popup(s) with the page builder, and launch popup(s) on any page you want."

The number of pop-up features and options will not disappoint:

  • trigger modes
  • popup positions
  • launching management
  • popup import and export
  • and much, much more

As popup WordPress plugins go, Fancy Popup - Popup Plugin For WordPress is an exceptional plugin. The fact that it's compatible with Easy Digital Downloads and extremely useful for e-commerce just adds to its usefulness.

Conclusion

As someone who has used Easy Digital Downloads extensively, I can tell you that it is a solid platform that has been built with great care. From the moment you install the plugin, you quickly realize that this is a digital-download-focused e-commerce solution.

With time, I am sure we will see more and more useful Easy Digital Download extensions. There are also many Easy Digital Downloads WordPress themes already available, giving users the power to craft and create their own unique digital download e-commerce store.

Have you used Easy Digital Downloads before?

Categories: Web Design

Understanding ExpressJS Routing

Thu, 12/07/2017 - 04:00
Introduction

Express is a popular Node.js web framework. Amongst its functionality, it provides a wrapper for Routing. The Express Router helps in the creation of route handlers. In this tutorial, you will learn how to work with Express Router.

Let's get started.

Create a new directory for your application. Run the command to initialize npm in the directory you just created.

npm init -y

The only dependency you will need is express, so go ahead and install it.

npm install --save express

At the end, your package.json file should look like this.

#package.json { "name": "express-router", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "express": "^4.16.2" } }

Now create a new file called index.js, which will be your entry file as stated in your package.json.

For now, you just need a basic setup like this:

#index.js const express = require('express') const app = express() app.listen(3000, () => { console.log(`Server running at port 3000`) })Basic Routing

Start by creating some basic routes as I have below.

#index.js ... const router = express.Router() // 1 router.get('/', (req, res) => { // 2 res.send('This is the homepage!') }) router.post('/contact', (req, res) => { // 3 res.send('This is the contact page with a POST request') }) app.use('/', router) // 4 ...
  1. An instance of Express Router is created. The instance is set to a variable called router. This variable will be used whenever you want to create a route.
  2. A new route is defined for the GET method to the root of the application. It is attached to the instance of the Express Router class.
  3. A new route is defined for the POST method to the contact page of the application. It is attached to the instance of the Express Router class.
  4. This mounts some middleware that will be used to handle your routes. Here you tell your app that you want to make use of the router (which is the instance of the Express Router) for every request made to the app that corresponds to the path '/'. If you fail to mount a path on this middleware, it will be executed for every request made to the app.

Let's say you had the code below instead.

app.use('/user', router)

This will match all the following: /user/profile, user/profile/edit, user/dashboard/article/view, and so on.

Route Methods

In the above code, you attached a route method to an instance of Express Router. The route method is derived from one of the HTTP methods and attached to the instance of the Express Router as you did.

Express supports the following routing methods that correspond to HTTP methods: get, post, put, head, delete, options, trace, copy, lock, mkcol, move, purge, unlock, report, mkactivity, checkout, merge, m-search, notify, subscribe, unsubscribe, patch, and search.

There is a routing method app.all() which is not derived from any HTTP method. This routing method gets loaded for functions at a specified path for all request methods.

Say you have the code below in your application.

app.all('/books', (req, res) => { res.send('This accesses the book section') })

This will be executed for requests to "/books" when you are using GET, POST, PUT, or any HTTP request method.

Route Paths

A route path is used to define an endpoint where requests can be made. It does so with the combination of a request method. In Express, route paths can be string patterns or regular expressions.

Here are examples you can add to your index.js file.

#index.js router.get('/about', (req, res) => { res.send('This route path will match to /about') }) router.get('/profile.txt', (req, res) => { res.send('This route will match to /profile.txt') })

Let's see a route path using string patterns.

router.get('/ab+xy', (req, res) => { // 1 res.send('ab+xy') }) router.get('/ab(xy)?z', (req, res) => { // 2 res.send('/ab(xy)?z') })
  1. The route will match abxy, abbxy, abbbxy, and so on.
  2. The route will match /abz and /abxyz.
Route Parameters

These are used to capture values that are specified at a certain position in the URL. They are called URL segments. The values captured are made available in the req.params object, using the name of the route parameter specified in the path as the keys of the values.

Here is an example.

If you have a route path similar to this in your application: /users/:userId/articles/:articleId

The requested URL will look like this: http://localhost:3000/users/19/articles/104

In the req.params, the following will be available: { "userId": "19", "bookId": "104" }

Go ahead and create a new route in your application, using the route path above.

router.get('/users/:userId/articles/:articleId', (req, res) => { res.send(req.params) })

Start your server and point your browser to http://localhost:3000/users/19/articles/104. You will see the req.params object displayed in your browser.

The name of the route parameters must be made up of word characters ([A-Za-z0-9_]).

Let's take it further!

Say you want to have a route path called /users/:name, where the name of the user is passed into the URL and the application displays the name along with a string. How do you think that can be achieved?

Go ahead and try it out on your own first.

Here is what the route should look like.

router.get('/users/:name', (req, res) => { res.send(`Welcome, ${req.params.name}!`) })

When you visit http://localhost:3000/users/vivian, you should see Welcome, vivian! displayed in the browser.

Login Routes

Let's see how to create a login route in Express. Your login routes require two actions on a single route path. The actions will be differentiated by the route method used. Here is how it will look.

router.get('/login', (req, res) => { res.send('This is should lead to the login form') }) router.post('/login', (req, res) => { res.send('This is used in processing the form') })

After doing this, your store form should have an action whose value is the route defined with the HTTP POST method. Here is how it should look.

<form action="/login" method="POST"> </form>

When the submit button of the form gets clicked, the specified router gets called. The difference between both route paths as stated above is the HTTP POST. This is how the application determines which is responsible for handling the data passed through the form.

Another aspect where this can be experienced is in the area of editing and updating resources.

app.route()

app.route() can be used to create a chain of route handlers for a specific route path.

Using the example of the login route, here is how you will make use of app.route().

app.route('/login') .get((res, req) => { res.send('This is should lead to the login form') }) .post((res, req) => { res.send('This is used in processing the form') })

You can add more route handlers than we have above.

Conclusion

At this point, you should know how routing works in Express. You have learned how to set up basic routing, and also how to work with route methods and paths. You saw how to make use of route parameters and retrieve values sent via the URL.

If you’re looking for additional JavaScript resources to study or to use in your work, check out what we have available on Envato Market.

With this knowledge, you can go further to build an Express application with complex routing.

Categories: Web Design

Task Scheduling in Laravel

Mon, 12/04/2017 - 04:00

In this article, we’ll go through one of the exciting features of the Laravel web framework—task scheduling. Throughout the course of this article, we’ll look at how Laravel allows you to manage scheduled tasks in your application. Moreover, we’ll also end up creating our own custom scheduled tasks for demonstration purposes.

The Laravel framework allows you to set up scheduled tasks so that you don't have to worry about setting them up at the system level. You can get rid of that complex cron syntax while setting up scheduled tasks since Laravel allows you to define them in a user-friendly way.

We’ll start the article with how you are used to setting up traditional cron jobs, and following that we’ll explore the Laravel way of achieving it. In the latter half of the article, we’ll give it a try by creating couple of custom scheduled tasks that should provide hands-on insight into the subject.

Traditional Scheduled Task Setup

In your day-to-day application development, you often face a situation that requires you to execute certain scripts or commands periodically. If you're working with the *nix system, you are probably aware that cron jobs handle these commands. On the other hand, they're known as scheduled tasks on Windows-based systems.

Let's have a quick look at a simple example of the *nix based cron job.

*/5 * * * * /web/statistics.sh

Pretty simple—it runs the statistics.sh file every five minutes!

Although that was a pretty simple use case, you often find yourself in a situation that requires you to implement more complex use cases. On the other hand, a complex system requires you to define multiple cron jobs that run at different time intervals.

Let's see some tasks a complex web application has to perform periodically in the back-end.

  • Clean up the unnecessary data from the database back-end.
  • Update the front-end caching indexes to keep it up-to-date.
  • Calculate the site statistics.
  • Send emails.
  • Back up different site elements.
  • Generate reports.
  • And more.

So, as you can see, there's plenty of stuff out there waiting to be run periodically and also at different time intervals. If you're a seasoned system admin, it's a cake walk for you to define the cron jobs for all these tasks, but sometimes we as developers wish that there was an easier way around.

Luckily, Laravel comes with a built-in Task Scheduling API that allows you to define scheduled tasks like never before. And yes, the next section is all about that—the basics of Laravel task scheduling.

The Laravel Way

In the earlier section, we went through the traditional way of setting up cron jobs. In this section, we'll go through the specifics of Laravel in the context of the Task Scheduling API.

Before we go ahead, the important thing to understand is that the scheduling feature provided by Laravel is just like any other feature and won't be invoked automatically. So if you're thinking that you don't need to do anything at the system level then you're out of luck, I'd say.

In fact, the first thing you should do should you wish to use the Laravel scheduling system is to set up the cron job that runs every minute and calls the artisan command shown in the following snippet.

* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1

The above artisan command calls the Laravel scheduler, and that in turn executes all the pending cron jobs defined in your application.

Of course, we are yet to see how to define the scheduled tasks in your Laravel application, and that's the very next thing we'll dive into.

It's the schedule method of the App\Console\Kernel class that you need to use should you wish to define application-specific scheduled tasks.

Go ahead and grab the contents of the app/Console/Kernel.php file.

<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ 'App\Console\Commands\Inspire', ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->command('inspire')->hourly(); } }

As you can see, the core code itself provides a useful example. In the above example, Laravel runs the inspire artisan command hourly. Don't you think that the syntax is so intuitive in the first place?

In fact, there are a couple of different ways in which Laravel allows you to define schedule tasks:

  • Use the closure/callable.
  • Call the artisan command.
  • Execute the shell command.

Moreover, there are plenty of built-in scheduling frequencies you could choose from:

  • every minute/every five minutes
  • hourly/daily/weekly/quarterly/yearly
  • at a specific time of the day
  • and many more

In fact, I would say that it provides a complete set of routines so that you don't ever need to touch the shell to create your custom cron jobs!

Yes I can tell that you're eager to know how to implement your custom scheduled tasks, and that is what I also promised at the beginning of the article.

Create Your First Scheduled Task in Laravel

As we discussed, there are different ways in which Laravel allows you to define scheduled tasks. Let's go through each to understand how it works.

The Closure/Callable Method

The scheduling API provides the call method that allows you to execute a callable or a closure function. Let's revise the app/Console/Kernel.php file with the following code.

<?php namespace App\Console; use Illuminate\Support\Facades\DB; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { // the call method $schedule->call(function () { $posts = DB::table('posts') ->select('user_id', DB::raw('count(*) as total_posts')) ->groupBy('user_id') ->get(); foreach($posts as $post) { DB::table('users_statistics') ->where('user_id', $post->user_id) ->update(['total_posts' => $post->total_posts]); } })->everyThirtyMinutes(); } }

As you can see, we've passed the closure function as the first argument of the call method. Also, we've set the frequency to every 30 minutes, so it'll execute the closure function every 30 minutes!

In our example, we count the total posts per user and update the statistics table accordingly.

The Artisan Command

Apart from the closures or callables, you could also schedule an artisan command that will be executed at certain intervals. In fact, that should be the preferred approach over closures as it provides better code organization and reusability at the same time.

Go ahead and revise the contents of the app/Console/Kernel.php file with the following.

<?php namespace App\Console; use Illuminate\Support\Facades\Config; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ 'App\Console\Commands\UserStatistics' ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { // artisan command method $schedule->command('statistics:user')->everyThirtyMinutes(); } /** * Register the Closure based commands for the application. * * @return void */ protected function commands() { require base_path('routes/console.php'); } }

It's the command method that you would like to use should you wish to schedule an artisan command as shown in the above code snippet. You need to pass the artisan command signature as the first argument of the command method.

Of course, you need to define the corresponding artisan command as well at app/Console/Commands/UserStatistics.php.

<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; class UserStatistics extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'statistics:user'; /** * The console command description. * * @var string */ protected $description = 'Update user statistics'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { // calculate new statistics $posts = DB::table('posts') ->select('user_id', DB::raw('count(*) as total_posts')) ->groupBy('user_id') ->get(); // update statistics table foreach($posts as $post) { DB::table('users_statistics') ->where('user_id', $post->user_id) ->update(['total_posts' => $post->total_posts]); } } }The Exec Command

We could say that the methods we've discussed so far were specific to the Laravel application itself. Moreover, Laravel also allows you to schedule the shell commands so that you could run external applications as well.

Let's go through a quick example that demonstrates how to take a backup of your database every day.

<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { // exec method $host = config('database.connections.mysql.host'); $username = config('database.connections.mysql.username'); $password = config('database.connections.mysql.password'); $database = config('database.connections.mysql.database'); $schedule->exec("mysqldump -h {$host} -u {$username} -p{$password} {$database}") ->daily() ->sendOutputTo('/backups/daily_backup.sql'); } }

It's apparent from the code that you need to use the exec method of the scheduler, and you need to pass the command that you would like to run as its first argument.

Apart from that, we've also used the sendOutputTo method that allows you to collect the output of the command. On the other hand, there's a method, emailOutputTo, that allows you to email the output contents!

And that brings us to the end of the article. In fact, we've just scratched the surface of the Laravel Scheduling API, and it has a lot to offer in its kitty.

Conclusion

Today, we went through the task scheduling API in the Laravel web framework. It was fascinating to see how easily it allows you to manage tasks that need to be run periodically.

At the beginning of the article, we discussed the traditional way of setting up scheduled tasks, and following that we introduced the Laravel way of doing it. In the latter half of the article, we went through a couple of practical examples to demonstrate task scheduling concepts.

I hope that you’ve enjoyed the article, and you should feel more confident about setting up scheduled tasks in Laravel. For those of you who are either just getting started with Laravel or looking to expand your knowledge, site, or application with extensions, we have a variety of things you can study in Envato Market.

Should anything pop up in your mind, let’s start a conversation using the feed below!

Categories: Web Design

Inheritance and Extending Objects With JavaScript

Thu, 11/30/2017 - 05:00

If you are familiar with object-oriented programming, you are most likely familiar with subclassing and inheritance. However, inheritance has been getting a bad rap. I believe that is because some developers see it as a catch-all solution when you need to modify a program. The problem with this is that class hierarchies can become unmanageable. 

There are other design patterns we can use to make our apps easier to understand and ready for change. I will show you examples of how you can use inheritance and the decorator and composite pattern to improve your program's design.

Inheritance

The idea behind inheritance is that one object "is a" specialized version of another object. There is a parent class (also known as a superclass) which defines the base properties of our object. And there is a child class (subclass) that inherits the properties of the parent class. 

An example of inheritance is a dog and a poodle. All dogs have certain features like four legs and the ability to bark. A poodle “is a” kind of dog. An SUV is a vehicle. A circle is a shape. This is what our class hierarchy would look like if we were designing a program for creating shapes.

The benefit of having a Shape class is that we can reuse the properties and methods we defined in other classes. 

Notice that the getArea method was redefined in each of our subclasses. We did not have to redefine this method, but we did it to replace our parent's implementation of the method. That is because each shape will have its own way of calculating the area. 

Overriding a parent method in a child class is an example of polymorphism. Polymorphism is the ability for objects to have multiple forms. It allows subclasses to have methods with the same name as their superclass but with different implementations.  

This is an example of what our code would look like for creating a Shape and Circle subclass:

class Shape { constructor(x, y) { this.xPosition = x; this.yPosition = y; } getArea() {...} } class Circle extends Shape { constructor(x, y, radius) { super(x, y, radius); this.radius = radius } getArea() {...} } let circle = new Circle(1,2,3);

One of the drawbacks to this design choice is that if you decide the parent class needs to change, then the subclasses may need to change too, along with all the objects we created. 

For example, suppose we decided later on that it would be better to replace the x and y parameters of the Shape class with an object. Consequently, we would need to change the constructor for all of our subclasses and the arguments for every object we instantiated.

We can see how this can easily become problematic. We would have to make sure we got our design right the first time around so that we could avoid making a change. But that is not practical, nor is it what we should be striving for. A program is an ever-evolving entity, and it’s better for us developers if we have the flexibility to make changes easily. At the very least, we should not have more than one level of child classes.

Decorator Pattern

A decorator allows us to attach properties to an object after they have been created. This means we can add functionality without subclassing or being concerned with the implementation of our object. 

Instead of thinking a circle is a shape, we could use the Shape class to create circles and wrap it with the additional properties we want. Here is an alternative to creating circle objects using a decorator:

class Shape { constructor(data) { this.x = data.x; this.y = data.y; } getArea() {...} } function CircleDecorator(shape) { shape.radius = 3; shape.getArea = function() {...}; return shape; } let shape = new Shape({x:1,y:2}); let circle = new CircleDecorator(shape);

We can add or modify members of our Shape class with a decorator as opposed to subclassing it. With our shapes example, you might find that you just want to create a circle object that has all of the properties you need and do the same for other shapes. That is fine. But a decorator allows us to reuse the code in our Shape class and modify it with the functionality that differs with each shape. As a result, we will have more objects, but more objects are easier to manage than more subclasses.

This pattern is not limited to creating graphics. You can use it in any situation where you want to add responsibilities to an object. 

For example, we may have a class that handles signing up users to our account. Before we save their information to our database, it would be wise to check that the input is valid and doesn’t contain any malicious scripts. We could decorate the class with a method to validate the information first. This same decorator can be reused anywhere in our application where we accept user input.

Composite Pattern

Objects can be composed of other objects. The view for an app can be thought of as a component that is composed of other views. If we were making a game, our game world would display all our graphics we created like circles and squares. Every time we update our view, we would need to redraw every element. We need a way to manage all of the elements as a group. 

That is where the composite pattern can help us. We can create a class that is responsible for all of the elements. When we want to redraw the elements, we call this class’s draw method, and it will call the draw method on each individual element.  

class Component { constructor(name){ this.components = []; this.element = document.createElement(name); } add(elem) { this.components.push(elem); } draw() { for (const elem of this.components) { elem.draw(); } } } class Circle { constructor(data) { this.x = data.x; this.y = data.y; this.radius = data.radius; } getArea() {...} draw() {...} } let world = new Component('div'); let circle = new Circle({x: 1, y:1, radius: 2}); let circle2 = new Circle({x: 10, y:10, radius: 2}); world.add(circle); world.add(circle2); world.draw();

A webpage can also be thought of as a component. This component could have a menu, a sidebar, and a blog post. The post would be a sub-component that has a picture, a title, and a body. The draw method for our main app component will call draw on the menu, sidebar, and post. The post component will in turn call draw on the post image, title, and body. 

Here is a view of what a web page would like divided into components:

This pattern isn’t limited to creating views. For example, if we were making a game, we might have a component to manage the elements on the screen, a component to manage the audio, and a component to manage the game state. 

These would all be inside a component I call the game engine. The game engine would have an initialize method that would call the initialize method on each of its sub-components. That is the power in using the composite pattern. Instead of dealing with individual objects, we can treat them as one object.  

Conclusion

Inheritance lets us reuse code by defining an object in terms of another object. The decorator pattern allows us to add responsibilities to an object without changing the original code or subclassing. The composite pattern models part-whole relationships. These patterns aren’t meant to be used in isolation. 

JavaScript has become the language of working on the web. It’s not without its learning curves, and there are plenty of frameworks and libraries to keep you busy, as well. If you’re looking for additional resources to study or to use in your work, check out what we have available on Envato Market.

They can be combined as you see fit. The examples I provided also should not be taken as the only application for using the patterns. They are just a guide. Feel free to use your creativity to apply them. There is no one way to implement them or one use case.

Categories: Web Design

Performant Animations Using KUTE.js: Part 5, Easing Functions and Attributes

Fri, 11/24/2017 - 04:00

So far in this series, you have learned how to animate the CSS properties of different elements, how to create different SVG-related animations, and how to animate the text content of different elements on a webpage. There is one more way in which you can animate the elements on a webpage using KUTE.js, and that is by changing the values of different attributes. This requires you to include the attributes plugin in your project.

In this tutorial, you will learn how to use the attributes plugin to animate the value of different kinds of attributes in KUTE.js. We will also discuss different easing functions that you can use to control the pace of different animations.

Easing Functions

Objects in real life very rarely move linearly. They are either accelerating or decelerating. Even the acceleration and deceleration occur at different magnitudes. Up to this point, all our animations have progressed linearly. This doesn't feel natural at all. In this section, you will learn about all the easing functions that KUTE.js provides for controlling the pace of different animations.

The core easing functions in the library are included in the core engine out of the box. Let's say you want to apply the QuadraticInOut easing to an animation. This can be achieved in two ways:

easing: KUTE.Easing.easingQuadraticInOut // OR easing: 'easingQuadraticInOut'

Each of the easing functions has a unique curve that determines how the elements will accelerate during the animation. A sinusoidal curve implies linear acceleration. Keep in mind that this is different from the linear easing function. The linear function implies a linear speed of animation, while a sinusoidal curve implies a linear speed of acceleration for the animation. In other words, the speed of the animation will increase or decrease linearly. Similarly, quadratic implies acceleration with a power of two, cubic implies a power of three, quartic implies a power of four, and quintic implies a power of five. There are also circular and exponential easing functions.

You can append In, Out, or InOut to any of the easing functions. The value In implies that the animation will start very slowly and keep accelerating until the end. The value Out implies that the animation will start at the maximum speed and then decelerate slowly until it comes to a halt at the end. The value InOut means that the animation will speed up at the beginning and slow down at the end.

You can also use bounce and elastic easing functions in your animations and append In, Out, or InOut to any of them. In the following demo, I have applied all these easing functions on different circles so that you can see how they affect the pace of the animation.

It is possible that none of the core easing functions provide the animation pace that you are looking for. In such cases, you can include the Cubic Bezier functions in your project from the experiments branch and start using those easing functions. 

Similarly, KUTE.js also provides some physics-based easing functions imported from the Dynamics.js library. You can read more about all these easing functions and how to properly use them on the easing function page of the library.

Animating Attributes

Attributes in SVG can accept numbers as well as strings as their value. The strings can be color values or numbers suffixed with a unit like px, em, or %. The names of the attributes themselves can also consist of two words joined by a hyphen. Keeping these differences in mind, KUTE.js provides us different methods that can be used to specify the values of different attributes.

var tween = KUTE.to('selector', {attr: {'r': 100}}); var tween = KUTE.to('selector', {attr: {'r': '10%'}}); var tween = KUTE.to('selector', {attr: {'stroke-width': 10}}); var tween = KUTE.to('selector', {attr: {strokeWidth: 10}});

As you can see, suffixed values need to be enclosed within quotes. Similarly, attributes which contain a hyphen in their name need to be enclosed inside quotes or specified in camelCase form.

Unitless Attributes

A lot of attributes accept unitless values. For example, the stroke-width of a path could be unitless. Similarly, you don't have to specify a unit for the r, cx, and cy attributes of a circle element. You can animate all these attributes from one value to another using the attributes plugin. 

Now that you know how to use different easing functions, you will be able to animate different attributes at different paces. Here is an example:

var radiusAnimation = KUTE.allTo( "circle", { attr: { r: 75 } }, { repeat: 1, yoyo: true, offset: 1000, easing: 'easingCubicIn' } ); var centerxAnimationA = KUTE.to( "#circle-a", { attr: { cx: 500 } }, { repeat: 1, yoyo: true, easing: 'easingCubicInOut', } ); var centerxAnimationB = KUTE.to( "#circle-b", { attr: { cx: 100 } }, { repeat: 1, yoyo: true, easing: 'easingCubicInOut' } ); var centeryAnimation = KUTE.allTo( "circle", { attr: { cy: 300 } }, { repeat: 1, yoyo: true, offset: 1000, easing: 'easingCubicOut' } );

The first tween animates the radius of both circles at once using the allTo() method we discussed in the first tutorial. If set to true, the yoyo attribute plays the animation in the reverse direction. 

The cx attribute of both the circles is animated individually. However, they are both triggered by the same button click. Finally, the cy attribute of both the circles is animated at once with an offset of 1000 milliseconds.

Color Attributes

Starting from version 1.5.7, the attribute plugin in KUTE.js also allows you to animate the fill, stroke, and stopColor attributes. You can use valid color names or hex values for the colors. You can also provide the color values in RGB or HSL format. 

One important thing that you have to keep in mind is that the animations will only seem to work if you are not setting the value of these properties in CSS. In the following demo, the fill color wouldn't have animated at all if I had added the following CSS in our demo.

rect { fill: brown; }

The demo I created is very basic, but you can make it more interesting by applying transforms and using more colors.

Suffixed Attributes

A lot of SVG attributes like r and stroke-width can work with and without suffixes. For example, you can set the value of r to be a number like 10 or in terms of em units like 10em. There are some attributes like offset attribute for color stops that always require you to add a suffix. While specifying a value for suffixed attributes in KUTE.js, always make sure that you enclose the value within quotes.

In the following example, I have animated the offset value of the first stop in a gradient and the color of the second stop. Since offset requires a suffix, I have enclosed the value inside quotes.

var offsetAnimation = KUTE.allTo( ".stop1", { attr: { offset: '90%'} }, { repeat: 1, offset: 1000, yoyo: true, easing: 'easingCubicIn' } ); var colorAnimation = KUTE.allTo( ".stop2", { attr: { stopColor: 'black'} }, { repeat: 1, offset: 1000, yoyo: true, easing: 'easingCubicIn' } ); var scaleAnimation = KUTE.allTo( "circle", { svgTransform: { scale: 2} }, { repeat: 1, offset: 1000, yoyo: true, easing: 'easingCubicIn' } );

There are three different gradients in the demo, and each of these gradients has two color stops with the class names stop1 and stop2. I have also applied a scale transform using the svgTransform attribute, which we discussed in the third tutorial of the series.

Final Thoughts

In this tutorial, you learned about different easing functions available in KUTE.js and how you can use them to control the pace of your own animations. You also learned how to animate different kinds of attributes.

I have tried to cover all the important aspects of KUTE.js in this series. This should be enough to help you use KUTE.js confidently in your own projects. You can also read the documentation in order to learn more about the library. 

I would also recommend that you go through the source code and see how the library actually works. If you have any questions or tips related to this tutorial, feel free to share them in the comments.

Categories: Web Design

Performant Animations Using KUTE.js: Part 4, Animating Text

Thu, 11/23/2017 - 04:00

In the second tutorial of this series, you learned how to animate different CSS properties of the elements on a webpage using KUTE.js. You learned how to animate all the transform properties as well as properties like border-radius and border-color. You can also use the CSS plugin to animate CSS properties like font-size, line-height, letter-spacing, and word-spacing.

KUTE.js also has a Text plugin which allows you to animate the text inside different elements, either by increasing or decreasing a number like in a countdown or by writing a string character by character.

In this tutorial, you will learn how to animate the text inside different elements on a webpage using the CSS and Text plugins in KUTE.js.

Animating CSS Text Properties

As I mentioned earlier, you can use the KUTE.js CSS plugin to animate four different text-related CSS properties. These properties are font-size, line-height, letter-spacing, and word-spacing. We will also use some properties from the core engine discussed in the first tutorial to animate individual letters. Let's see how we can use all these concepts together to create the vibrating HELLO text in the following demo.

Here is the code that was used to create the above animation:

var theLetters = document.querySelectorAll("span"); var h = document.querySelector(".h"); var e = document.querySelector(".e"); var la = document.querySelector(".la"); var lb = document.querySelector(".lb"); var o = document.querySelector(".o"); var startButton = document.querySelector(".start"); var animateColor = KUTE.allFromTo( theLetters, { color: 'white' }, { color: 'red' }, { offset: 200, duration: 50} ); var animateFontSize = KUTE.allFromTo( theLetters, { fontSize: '2em' }, { fontSize: '4em' }, { offset: 100, duration: 200, repeat: 10, yoyo: true} ); var animateSkewing = KUTE.allTo( theLetters, { skewX: -15}, { offset: 200, duration: 200 } ); var animateH = KUTE.to( h, { color: '#009688' } ); var animateE = KUTE.to( e, { translateY: -40, color: '#E91E63' } ); var animateLA = KUTE.to( la, { color: '#8BC34A' } ); var animateLB = KUTE.to( lb, { translateY: 20, color: '#FFC107' } ); var animateO = KUTE.to( o, { color: '#FF5722' } ); var lettersSqueezed = KUTE.allTo( theLetters, { letterSpacing: '-15px' }, { offset: 0, duration: 200 } ); animateColor.chain(animateFontSize); animateFontSize.chain(animateSkewing); animateSkewing.chain(animateH, animateE, animateLA, animateLB, animateO); animateE.chain(lettersSqueezed); startButton.addEventListener( "click", function() { animateColor.start(); }, false );

Each letter of the word is wrapped inside a span tag and has its own unique class. The first tween animates the color of all the letters from white to red with an offset of 200ms. This is also the first animation that is played after clicking on Start Animation. The animateFontSize tween has been chained to animateColor. This way, the font-size animation begins as soon as the color animation ends. 

You might have noticed that I have used two attributes called repeat and yoyo to control the behavior of the animation. The yoyo attribute is used to reverse the animation that is currently being played repeatedly. This can avoid sudden jumps in the values of different properties during the animation and make it appear smooth.

The font-size animation has been chained with animateSkewing, which skews all the letters by -15 degrees. The skewX and skewY properties are available within the core engine itself.

All the tweens for animating the color of different letters have been chained to animateSkewing at once. This way, you can make sure that all the chained color animations start playing as soon as the skew animation ends. Finally, the lettersSqueezed tween reduces the spacing between different letters by 15 px.

You can create more interesting effects by using different combinations of properties.

Animating Numbers

You can also animate numbers in KUTE.js. However, you will have to include an additional text plugin to create the animation. 

The process of animating numbers is actually very simple. You just need to specify the selector where the animating numbers should be shown as well as the final number at which the animation should end. 

Here is a basic example that shows the total number of airports in the USA in 2016 using animation.

var usa = document.querySelector(".usa"); var startButton = document.querySelector(".start"); var animateUSA = KUTE.to( usa, { number: 19536 } ); startButton.addEventListener( "click", function() { animateUSA.start(); }, false );

You can also apply the usual tween options like duration, repeat, and delay to customize the behavior of the animation. The code we just wrote will result in the following animation:

Writing Text Character by Character

This is a very popular effect that you can find on quite a few websites. The KUTE.js text plugin allows you to specify the new sentence that should replace the original sentence one character at a time. 

Before replacing the initial characters with their final value, random characters are animated like the numbers example you just saw. The embedded CodePen demo should make it clearer:

Here is the code that you need to write in order to create the above animation:

var animateHeading = KUTE.to( heading, { text: '70% Surface of Earth is Covered with Water.' }, { duration: 5000} ); startButton.addEventListener( "click", function() { animateHeading.start(); }, false );

The character animation for the whole sentence is finished within 5 seconds. As you might have noticed, the initial and final sentences don't need to have the same number of characters. This gives us a lot of liberty when setting the value of the text parameter.

You can also include HTML tags inside the value of the text parameter and then use CSS to change the appearance of the text that you just animated.

var animateHeading = KUTE.to( heading, { text: '70% SURFACE OF <span class="earth">EARTH</span> IS COVERED WITH <span class="water">WATER</span>.' }, { duration: 10000, textChars: 'upper' } );

There will be a delay in the appearance of Earth after of has already appeared. This happens because the plugin also writes <span class="earth"> using the same character animation, but none of those characters are actually visible to the user. The delay may or may not be desirable based on your preferences.

The intermediate characters that are shown during the animation are lowercase alphabetical values by default. This can be an issue when the characters that you want to animate are all uppercase letters or numbers. Which intermediate characters are used for the animation is determined by the value of the textChars parameter. It accepts six different values:

  • alpha: In this case, the intermediate characters will be lowercase letters.
  • upper: In this case, the intermediate characters will be uppercase letters.
  • numeric: In this case, numerical characters are used for the animation. This is different from animating a number as the values won't increase sequentially.
  • symbols: In this case, the plugin will use characters like #, %, and $ for the animations.
  • all: You can use this value if you want the intermediate characters to be a mix of alphabetic, numeric, and symbols.
  • If nothing else works for you, KUTE.js gives you the option of specifying your own custom list of characters that should be used during the animation.

The following example shows how you can animate text inside a heading using uppercase intermediate characters.

Final Thoughts

In this tutorial, you learned how to use the CSS and Text plugins in KUTE.js to animate the text inside an element. When you want to animate the appearance of the text, you need to use the CSS plugin. This will allow you to use properties like font-size, letter-spacing, etc. When you want to change the actual characters inside any element, you need to use the text plugin.

If you’re looking for additional JavaScript resources to study or to use in your work, check out what we have available on Envato Market.

I hope you learned something new in this tutorial. If you have any questions, please let me know in the comments.

Categories: Web Design

Pages