Categories
Intermediate

DO THIS!! Instead of using AJAX for WordPress Async requests

If you ever had to build asynchronous interfaces for WordPress, you may have opted to use AJAX requests. Today I’ll talk about the drawbacks of this approach and introduce you to a better solution. 

First of all, if you have a need for just one or two ajax requests, then this post might not be for you. But if you manage a lot of data with AJAX then read on.

So what are the disadvantages of AJAX? Well, if you manage data entities using AJAX, then you probably need to write a lot of different handlers – create, update, delete, and so forth… This becomes a lot of work pretty fast. Secondly, you would need to write the code for success and error handling yourself. Granted, you have methods like wp_send_json and wp_send_error_json that make life easier, but wouldn’t it be nice to just return an error from your function and be done with it?

So what else is there? Easy, REST. WordPress allows you to build your own RESTful APIs. Using REST allows you to easily manage different actions for your data entities (POST, GET, DELETE…). You can manage secure access with REST easily. REST also makes error handling easier – simply return a WP_Error instance and WordPress will do all of the work for you.

If the above still hasn’t convinced you to move to REST, consider this: many javascript packages will support REST requests out of the box. take Angular packages such as @NgRx/data – they manage your data entities for you, requiring a lot less work for you, and they assume the existence of some REST interface. It’s quite impossible to think about how a 3rd party package may have support ajax requests, as these are not predefined interfaces.

Finally – consider testing, npm packages like json-server mimic a RESTful API allowing you to simulate the production environment while testing.

To read about how to use REST interfaces with WordPress read here https://developer.wordpress.org/rest-api/.

So make your life easier and stop using AJAX today! 🙂 

Categories
Intermediate

Angular Typescript (async) Catch-Finally Decorator

Hey Guys! Today I want to talk about error handling for async and non-async Typescript methods. Let’s take a look at some error-prone typescript method:

someRegularMethod(){

// code
someDangerousMethod();
//more code
}

So what if some Dangerous Method threw an exception? Solution try-catch!

someRegularMethod(){
// code
try{
someDangerousMethod();

}catch(err)[

]
//more code

}

But this bloats the code a bit, right?

So what’s the alternative?  Catch Decorator. Click on the image below to access the code:

Using the catch decorator your code will look like this:

@Catch(Error, (err: Error, ctx) => ctx.handleError(err), (ctx) => ctx.finalizeRequest())
someRegularMethod(){

// code
someDangerousMethod();
//more code
}

This mimics the try-catch-finally block. The first parameter is the Error type, the second is the error handler, and the third is the finally block. This saves us the trouble to write it in the method itself.

You can even use it with async methods: 

@Catch(Error, (err: Error, ctx) =>  ctx.handleError(err), (ctx) => ctx.finalizeRequest())
async someRegularMethod(){
 
 // code
 await someDangerousMethod();
 //more code
}

So what do you think? Will you stop using regular try-catch blocks?

Categories
Intermediate

Amazon SES (How to Receive and Send Emails?)

Amazon  SES (Simple Email Service), can be configured to receive emails as well as sending them. We’ll describe the steps necessary to configure SES to receive emails and forward them to your personal mailbox. This tutorial assumes you have already verified your domain with Amazon SES:

We will do this through the SES Email Receiving menu on the bottom left.

Step 1 – Access the active rule set menu and store your emails

1) Click on Rule Sets

2) Click on View Active Rule Sets

We’ll set up some rules for an S3 bucket to hold our emails. S3 is a scalable cloud storage service.

3) Click on Create Rule

4) Choose recipient:

Enter the recipient email address. This is the address we will receive emails at (Not the final destination), For example, if your domain is example.com, you may enter admin@example.com. Note: the domain must be in the list of verified domains.

5) Choose S3:

6) Choose Create S3 Bucket:

7) Give your bucket some indicative name like “Store my emails”:

8) Go to the next step. Put the rule at the beginning:

9) You may need to create a default rule set:

10) Give the rule a nice name – “Email Store Rule”:

11) Go to the next step and approve.

Step 2 – Create Lambda (The code to forwards emails) 

1) Go to Amazon’s Lambda service and click “Create function”:

2) Choose node 12:

3) Create an environment variable:

4) Add an environment variable. Name the key to_address and enter your email (the one you want to forward to) in the value:

5) Head back to the configuration screen – Paste the following code to index.js:

Banjith De Silvabanjith

var AWS = require('aws-sdk');
//var forwardFrom = process.env.from_address;
var forwardTo = process.env.to_address;  
exports.handler = function(event, context) {
    var msgInfo = JSON.parse(event.Records[0].Sns.Message);
    // don't process spam messages
    if (msgInfo.receipt.spamVerdict.status === 'FAIL' ||         
        msgInfo.receipt.virusVerdict.status === 'FAIL') {
        console.log('Message is spam or contains virus, 
        ignoring.');
        context.succeed();
    }
 
    var email = msgInfo.content, headers = "From:    
    "+msgInfo.mail.destination[0]+"\r\n";
    headers += "Reply-To: 
    "+msgInfo.mail.commonHeaders.from[0]+"\r\n";
    headers += "X-Original-To: 
    "+msgInfo.mail.commonHeaders.to[0]+"\r\n";
    headers += "To: "+forwardTo+"\r\n";
    headers += "Subject: Fwd: 
    "+msgInfo.mail.commonHeaders.subject+"\r\n";
 
    if (email) {
        var res;
        res = email.match(/Content-Type:.+\s*boundary.*/);
        if (res) {
            headers += res[0]+"\r\n";
        }
        else {
            res = email.match(/^Content-Type:(.*)/m);
            if (res) {
                headers += res[0]+"\r\n";
            }
        }
 
        res = email.match(/^Content-Transfer-Encoding: 
        (.*)/m);
        if (res) {
            headers += res[0]+"\r\n";
        }
 
        res = email.match(/^MIME-Version:(.*)/m);
        if (res) {
            headers += res[0]+"\r\n";
        }
 
        var splitEmail = email.split("\r\n\r\n");
        splitEmail.shift();
 
        email =headers+"\r\n"+splitEmail.join("\r\n\r\n");
    }
    else {
        email = headers+"\r\n"+"Empty email";
    }
 
    new AWS.SES().sendRawEmail({
        RawMessage: { Data: email }
    }, function(err, data) {
        if (err) context.fail(err);
        else {
            console.log('Sent with MessageId: ' + 
            data.MessageId);
            context.succeed();
        }
    });
}

Step 3: Create SNS Topic

 1) Go to Amazon’s SNS service dashboard and create a new topic:

2) Give it some indicative name and click “Create topic”:

3) Go to the topic dashboard and click “Create subscription”:

4) For the protocol choose Lambda and use the Lambda we just created.

5) Click the “Create subscription button”:

Step 4 – Put it all together 

1) Back to the SES console, create another rule, call it ‘forward emails rule’.

2) This time for “Add Action” choose SNS, and choose the topic we created.

3) Implement the next rule, which is after the rule from Step 1

Test it! if it doesn’t work please let us know so we can fine-tune this tutorial.

Categories
Intermediate

Svelte App on a WordPress Admin Page??

Since I work a lot using WordPress, I was wondering if I could put a Svelte app on an admin WordPress page. As I found out, it’s not that complicated to achieve this – but you do need some tinkering. Initially, we must define the admin page as so:

add_menu_page( "Menu Name, "Menu Name, "manage_options", "menu_slug", function(){
 
	});

Notice I’m using an anonymous function to render the page. In the function I will enqueue the script and style of the app as follows:

add_menu_page( "Menu Name, "Menu Name, "manage_options", "menu_slug", function(){
             wp_enqueue_script( 'bundle_js',plugins_url( 'js/' . "bundle.js", __FILE__ )  ,array(), 1.1, true );
             wp_enqueue_style( "bundle_css",plugins_url( 'css/' . "bundle.css", __FILE__ ));
        });

This is almost adequate. But Svelte targets the body of the document, so some minor amendments will be needed to do the trick.

First, have Svelte target some unique tag in your main js file:

const app = new App({
	target: document.querySelector("my-special-tag")
});

Secondly, add one more piece of code to your add_menu_page call:

add_menu_page( "Menu Name, "Menu Name, "manage_options", "menu_slug", function(){
             echo "<my-special-tag/>"; // add this
             wp_enqueue_script( 'bundle_js',plugins_url( 'js/' . "bundle.js", __FILE__ )  ,array(), 1.1, true );
             wp_enqueue_style( "bundle_css",plugins_url( 'css/' . "bundle.css", __FILE__ ));
         });

That’s it! Providing that you copied the Svelte code to the relevant directories in your plugin- everything should work! I also recommend reading my post about Hash File Suffixing to prevent the browser from caching your scripts.

Categories
Beginner

Proper use of Arrays with UrlSearchParams

If you’re executing ‘get’ requests directly, you may sometimes need to send in an array of data. Below is an example of how to build the query string correctly using UrlSearchParamsmethod append:

var url = new URL(url ) // url is some url string

let searchParams =  new URLSearchParams({}); // you can pass in any initial data that you'd like here
let posts = get_my_post_array(); // returns an array of post ids
for(let post of posts){
    searchParams.append("post[]",post); // this is what 
    you need. Notice the square   brackets
}
url.search = searchParams.toString();
let json = fetch(url).then(response => response.json()); // and get the response

Now your back-end server will receive an array “post” with all the required Ids!

Thoughts? Comments? Let me know below.

Categories
Beginner

Sticky Headers with CSS and HTML

Hey Guys!! I wanted to see if I can extend this tutorial from w3schools. What they show here is how to create a sticky header that scrolls down with the top of the page. My goal here is to check if we require any javascript for this at all. I’m looking for this particular appearance. Notice that the first statement “I come before the rest” is visible at all times when it’s in the viewport.

So first, the HTML:

<h3>I come before the rest</h3>
<div class="header sticky" id="myHeader">
      <h2>My Header</h2>
</div>
<div class="content">
      <h3>On Scroll Sticky Header</h3>
      <p>
        The header will stick to the top when you reach 
        its scroll position.
      </p>
      <p>Scroll back up to remove the sticky effect.</p>
      <p>
        Some text to enable scrolling: “Lorem ipsum dolor 
        sit amet, illum definitiones no quo, maluisset 
        concludaturque et eum, altera fabulas ut quo. 
        Atqui causae gloriatur ius te, id agam omnis 
        evertitur eum. Affert laboramus repudiandae nec 
        et. Inciderint efficiantur his ad. Eum no
        molestiae voluptatibus”.
     </p>
 <!-- Many more of these paragraphs -->
 
   </div>

Secondly, the CSS:

.header {
  padding: 10px 16px;
  background: #555;
  color: #f1f1f1;
}
 
.content {
  padding-top: 102px;
}
 
.sticky {
  position: fixed;
  top: 0;
  width: 100%;
}

But there seems to be a problem, the statement on the top is hidden behind the header. That is because we used ‘fixed’ for the header position. Luckily, there is a very simple solution. Instead of using ‘fixed’ for the position, I will use ‘sticky’:

.sticky {
  position: sticky;
  top: 0;
  width: 100%;
}

Sticky will basically tell the browser to fix the header position only when it needs to (At the point of exiting the viewport). This way, the h3 header is now in its correct place and we’re done.

Thoughts? Comments? Let me know below!

Categories
Intermediate

Making Life Easier with wp_localize_script

wp_localize_script is a great way to face recurring challenges.We often need to enqueue a script that relies on data from the server (i.e. the database).

For example, say we want our script to store a list of all site category Ids in a variable. One way to do this would be to include a script tag in our HTML and then echo the data as a return value for a function as shown below:

// some HTML
<script>
function getCats(){
return '<?php echo json_encode(get_cat_ids())?>';
}
</script>
// some more HTML

But this method has many drawbacks. Firstly, we may not have any HTML that we want included. Secondly, we would need to add these types of functions for all kinds of data (trust me, I’ve been through it). 

This is exactly what wp_localize_script solves. Look at this alternative solution:

/ First I'm enqueuing a script, notice the handle of the script is "my_cool_script"
wp_enqueue_script( 'my_cool_script',plugins_url( 'js/my_cool_script.js' , __FILE__ )  ,array(), 1.0, true );
// Now I'm using wp_localize_scipt
wp_localize_script( 'my_cool_script', 'coolScriptData',  
   [
		'cat_ids' => get_cat_ids(),
   ] 
);

WordPress will now create a coolScriptData object which I can use inside my script directly.

Any comments? Thoughts? let me know in the comments.


Categories
Advanced

Hash File Suffixing

Adding a hash to a file suffix is a common way to force the browser to update its cache.

Angular for example offers this option by default in its build process. Whenever you bundle your code with Angular you will see a hash suffix to the bundled files, which are results of hash functions on the file contents. You can then immediately deploy these files about browser caching without concerns.But not all frameworks offer this. 

Svelte does not automatically bundle files with hash suffixes. You would need to install rollup-plugin-hash, for example. But I feel that a better method is to add the hash after bundling instead.

Often, after I bundle my code, I will need to copy it somewhere else on my machine before I deploy it to a live server.  To do this I use gulp. Gulp is a great tool to create tasks and automate your work. My copy-output task using Gulp looks like this:

var fs = require('fs');
var gulp = require('gulp');
const del = require('del'); 
 
var json = JSON.parse(fs.readFileSync('./dist_folder_details.json')); // this file contains the destination of the bundles on my machine
    gulp.task('copy-output', async () => {
       var distFolder = json['dist-folder-js'];
       await del([distFolder + '/**', '!' + distFolder], 
       {force: true}); // I used del ( 
       https://www.npmjs.com/package/del) to remove   
       the current content
       await new Promise((resolve, reject) => {
         gulp.src('./public/build/*.js')
         .pipe(gulp.dest(distFolder)) // I am copying the 
         new build files to the destination
         .on("end", resolve);
     });
});

So, all I need to do in order to add a hash suffix is to use gulp-hash:

var fs = require('fs');
var gulp = require('gulp');
const del = require('del');
var hash = require('gulp-hash'); // require it
 
var json = JSON.parse(fs.readFileSync('./dist_folder_details.json')); 
 
var json = JSON.parse(fs.readFileSync('./dist_folder_details.json')); 
gulp.task('copy-output', async () => {
    var distFolder = json['dist-folder-js'];
    await del([distFolder + '/**', '!' + distFolder], 
    {force: true}); 
    await new Promise((resolve, reject) => {
        gulp.src('./public/build/*.js')
        .pipe(hash()) // Use it
        .pipe(gulp.dest(distFolder)) 
        .on("end", resolve);
    });
});

Now hashing is integrated into my deploy process. No need to install framework-specific hashing packages.

Thoughts? Comments? Suggestions?  Please let me know below!!

Categories
Beginner

How to Setup a JSON Server?

This is the pattern I’m using when working with the json-server. Of course, you will first need to install it. You’d probably want to install it globally with using this piece of code:

npm i -g json-server

Then I find that the best way to set up my Db is to separate it into two files.

First I create a ‘data.js’ file to contain all of my data. For example, say that our data is products. The data.js file needs to look like:

let db = { 
	"products" :[
		{ title: "Product 1",},
		{ title: "Product 2",},
		{ title: "Product 3",},
		{ title: "Product 4",},
		{ title: "Product 5",},
		{ title: "Product 6",},
		{ title: "Product 7",},
		{ title: "Product 8",},
		{ title: "Product 9",}
	]
}
id = 1;
db.products.forEach(
	(product) => {
		product['id'] = id; id++; 
	}
);
module.exports = db;

Notice the module.export statement at the end. Additionally, I am adding Id’s to all of the products in a For loop (rather than setting it one-by-one), because json-server supports this field by default.

Then I require this module in db.js:

data = module.require("./data.js");
module.exports = () => data;

It’s more convenient for me to use two files, but we can probably store everything in db.js.

Finally, I will execute the json-server using the following piece of code:

json-server db/db.js --delay 2000

I’m also adding some delay to simulate actual server communication.

Json-server is a very cool tool that you can do a lot of stuff with. Comment below if you’ll have any issues or suggestions.

Categories
Beginner

Loading Animation with Fade Transition (Using Svelte)

Check out this cool animation block for Svelte. I’m fetching something from a random remote API as shown below. Notice that you need to chain two Promises using then to get the JSON response:

loading = fetch("http://localhost:3000/products").
then(response => response.json());

Then I will use the loading Promise with an async block:

{#await loading}       
	<div class="spinner-border" role="status">            
    		<span class="sr-only"></span>      
	</div>    
{:then results}        
	<div transition:fade> 
    		// display the result somehow       
	</div>    
{:catch error}       
	<p style="color: red">
		{error.message} // show an error 
	</p>  
{/await} 

What I’m doing is showing the loading animation until the result comes in, then I use fading animation to show the result. I’m also using catch to display error for the worst-case scenario. 

That’s it! If there is a better way to do this please let me know in the comments section.