Categories
JavaScript Answers

How to Warn User Before Leaving a Web Page with Unsaved Changes?

Sometimes, we need to warn users before leaving a web page when there’re unsaved changes in a form.

This way, the user won’t lose the form data when they leave a web page accidentally.

In this article, we’ll look at how to add a warning for the user before leaving a web page when there’re unsaved changes in a form.

Listen to the beforeunload Event

We can listen to the beforeunload event which is emitted when we leave a page.

And in the event handler, we can check if the form values have been changed and act accordingly.

For instance, we can write the following HTML to create a form:

<form>
  <input type='text'>
  <input type="submit" />
</form>

Then we can write the following JavaScript:

let isDirty = false
const input = document.querySelector('input[type="text"]')
input.addEventListener('change', () => {
  isDirty = true
})

window.addEventListener("beforeunload", (e) => {
  if (!isDirty) {
    return;
  }
  e.returnValue = true;
  return true
});

to check if the text input has been changed.

If it’s been changed, we set isDirty to true .

To determine this, we listen to the change event listener.

If it’s triggered, that means the input has been changed.

Next, we add the event listener for the beforeunload event.

In the event listener, we check if isDirty is true .

If it’s not, we use return to stop running the function.

Otherwise, we set e.returnValue to true to trigger the confirmation dialog to show.

We can’t change the content of that in modern browsers.

This works for more browsers.

Some browsers also trigger the dialog box by returning a truthy value.

Conclusion

We can listen to the beforeunload event to add a warning for the user when they leave a page with a form with unsaved changes.

Categories
JavaScript Answers

How to Deep Merge JavaScript Objects?

The Object.assign method or the spread operator lets us shallow merge JavaScript objects.

This means that only the first level is merged but the deeper are levels are still referencing the original object.

Deep merging ensures that all levels of the objects we merge into another object are copied instead of referencing the original objects.

In this article, we’ll look at how to deep merge JavaScript objects.

Merging Recursively

To deep merge JavaScript objects, we’ve to merge each level recursively ourselves.

To do this, we’ve to write our own function.

For example, we can write:

const isObject = (item) => {
  return (item && typeof item === 'object' && !Array.isArray(item));
}

const mergeDeep = (target, ...sources) => {
  if (!sources.length) return target;
  const source = sources.shift();

if (isObject(target) && isObject(source)) {
    for (const key in source) {
      if (isObject(source[key])) {
        if (!target[key]) Object.assign(target, {
          [key]: {}
        });
        mergeDeep(target[key], source[key]);
      } else {
        Object.assign(target, {
          [key]: source[key]
        });
      }
    }
  }

  return mergeDeep(target, ...sources);
}

const merged = mergeDeep({
  a: 1
}, {
  b: {
    c: 123
  }
});
console.log(merged)

First, we create the isObject helper function by checking if the item parameter is truthy and it’s an object that’s not an array.

We use the typeof operator to check if the object is an object.

If it’s truthy and its type is an object, then it must be an object.

Then we check that the object isn’t an array by using the Array.isArray method.

Next, we create the mergeDeep method to merge multiple objects into the target object.

To do this, we first check if there’re anything stored in sources .

If there’s none, then we return the target object since there’s no 2nd and subsequent arguments.

Next, we check if target and source are objects.

We get source by getting the first item from the source array with shift .

We loop through the keys of source with the for-in loop.

If the property is an object, then we merge an empty object into the target object with Object.assign .

Then we call mergeDeep to merge the keys inside the object property of source into the object recursively.

Otherwise, we have a primitive property value, and we call Object.assign to merge it into the object directly.

Finally, we return the merged object at the end.

Next, we try it by calling mergeDeep with 2 objects.

And we should see that merged is:

{
  "a": 1,
  "b": {
    "c": 123
  }
}

Lodash merge Method

If we don’t want to write our own function, then we can use the Lodash merge method to merge objects.

For instance, we can write:

const merged = _.merge({
  a: 1
}, {
  b: {
    c: 123
  }
});

And we get the same value for merged .

Conclusion

We can deep merge JavaScript objects with our own JavaScript function or the Lodash merge method.

Categories
JavaScript Answers

How to Get the Value of a Selected Radio Button with JavaScript?

Sometimes, we may want to get the value of a selected radio button in our JavaScript web app.

In this article, we’ll look at how to get the value of a selected radio button with JavaScript.

Loop Through the Radio Buttons to Find the One with the checked Property set to true

We can select all the radio buttons in a group and get the radio button that has the checked property set to true .

For instance, we can write the following HTML:

<div id="fruits">
  <input type="radio" name="fruit" value="apple"> Apple
  <input type="radio" name="fruit" value="orange"> Orange
  <input type="radio" name="fruit" value="grape" checked="checked"> Grape
</div>

Then we can get all the radio button elements with document.querySelectorAll and get the one that’s checked by writing:

const fruits = document.querySelectorAll('input[name="fruit"]')
for (const f of fruits) {
  if (f.checked) {
    console.log(f.value)
  }
}

fruits is an HTMLCollection object with all the radio button elements.

Then we use for-of to loop through the radio buttons.

In the loop body, we get the checked property of the radio button.

And we log the value of the one that’s checked.

Therefore, we should see 'grape' logged.

Use the :checked Selector

Another way to get the radio button that’s checked is to use the :checked selector.

For instance, we can write:

const selected = document.querySelector('input[name="fruit"]:checked').value;
console.log(selected)

to do this.

The input[name=”fruit”]:checked selector gets all the inputs with the attribute name fruit that is selected.

And we get the value attribute’s value with the value property.

So the value of selected should be 'grape' .

Get the Checked Value from the Form Values

We can also get the checked value of a radio button from the form values.

For instance, we can write:

<form id="fruits">
  <input type="radio" name="fruit" value="apple"> Apple
  <input type="radio" name="fruit" value="orange"> Orange
  <input type="radio" name="fruit" value="grape" checked="checked"> Grape
</form>

Then we get the radio button that’s checked by writing:

const form = document.getElementById("fruits");
console.log(form.elements["fruit"].value);

We get the form element with getElementById .

Then we get the inputs with the name attribute set to fruit with form.elements[“fruit”] .

And then we can get the value property to get the selected value.

So console log should log 'grape' .

Conclusion

There are several ways to get the checked value of a radio button with JavaScript.

Categories
JavaScript Answers

How to Create a JavaScript Array with the Same Element Repeated Multiple Times?

Sometimes, we may want to create a JavaScript array with the same repeated repeated multiple times as its content.

In this article, we’ll look at how to create a JavaScript array with the same element repeated multiple times.

For Loop and Array.prototype.push

We can use the for loop to run the push method to add an item to an array multiple times.

For instance, we can write:

const fillArray = (value, len) => {
  const arr = [];
  for (let i = 0; i < len; i++) {
    arr.push(value);
  }
  return arr;
}

const arr = fillArray(2, 5)
console.log(arr)

We create the fillArray function that has the value and len parameters.

value is the value we want to fill in the array.

len is the length of the returned array.

arr is the array with the repeated values.

After creating arr , we use the for loop to call push len times to push the same value to arr .

And after we call it, we get an array returned.

So arr is [2, 2, 2, 2, 2] since we fill the array with value 2 five times.

Array.prototype.fill

Another way to fill an array with a value repeatedly is to use the fill method.

It takes an argument with the value to fill.

We can combine this with the Array constructor to create an array with given length.

For instance, we can write:

const arr = Array(5).fill(2)
console.log(arr)

We call Array(5) to create an empty array with 5 empty slots.

Then we call fill with 2 to fill all the empty slots with 2.

And so arr is the same as the previous example.

Spread Operator and Array.prototype.map

Another way to create an array with a value repeated throughout the array is to use the spread operator and the map method.

For instance, we can write:

const arr = [...Array(5)].map((_, i) => 2)
console.log(arr)

We create an array with 5 empty slots with Array and spread it into the array.

And then we call map to return 2 in each slot.

And finally, we get the same result as before for arr .

Array.from

Array.from is another method that we can use to create an array filled with the same value throughout the array.

It works by creating an empty array and map the empty slots to the value we want.

For example, we can write:

const arr = Array.from({
  length: 5
}, i => 2)
console.log(arr)

We create an empty array with length 5 with Array.from .

Then in the 2nd argument, we pass in a callback to map the empty values to 2.

So we get the same result as before.

Lodash

We can use the times and constant Lodash methods to return an array that repeats a value throughout.

To do this, we write:

const arr = _.times(5, _.constant(2));
console.log(arr)

The constant method ensures that we repeat the element.

And so arr is the same value as the other examples.

We can do this more easily with the fill method.

To do this, we write:

const arr = _.fill(Array(5), 2);
console.log(arr)

We pass in the empty array into the first argument and the value to repeat in the 2nd argument.

Conclusion

We can use JavaScript array methods or Lodash methods to fill an array with the same value throughout.

Categories
JavaScript Answers

How to Convert UTC Date Time to Local Date Time?

Sometimes, we may want to convert a UTC date-time to a local date-time in our JavaScript apps.

In this article, we’ll look at how to convert UTC date-time to local date-time.

Add UTC after the Date String and Pass the String into the Date Constructor

One way to convert UTC date time to a local date-time is to just add the 'UTC' suffix to the date-time string.

Then we pass it into the Date constructor.

For instance, we can write:

const date = new Date('6/29/2021 4:52:48 PM UTC');
console.log(date.toString())

Then if we’re in the Pacific Time zone, we get:

Tue Jun 29 2021 09:52:48 GMT-0700 (Pacific Daylight Time)

logged.

The conversion is done automatically to local time as we can see.

Add Z after the Date String and Pass the String into the Date Constructor

The Z suffix is the same as UTC for setting a date-time to UTC.

We can attach this suffix to an ISO-8601 date-time since it is part of the standard.

For instance, we can write:

const date = new Date('2021-06-29T16:52:48.000Z');
console.log(date.toString())

Then we get:

Tue Jun 29 2021 09:52:48 GMT-0700 (Pacific Daylight Time)

as a result if we’re in Pacific Time.

Call getTimezoneOffset Method to Convert the Date Time to a Local Date Time

We can call getTimezoneOffset on a JavaScript date offset to get the time difference UTC and the local time zone in hours.

For instance, we can write:

const date = new Date('2021-06-29T16:52:48.000');
const newDate = new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000);
console.log(newDate)

We call getTime to get the timestamp for the date we want to convert.

Then we add the timezone offset in milliseconds we create with:

date.getTimezoneOffset() * 60 * 1000

Then we get the time zone offset and divide it by 60 to get the offset in hours.

And then we get:

Tue Jun 29 2021 02:52:48 GMT-0700 (Pacific Daylight Time)

as a result.

Conclusion

We can convert a UTC date-time into a local date-time with various date methods.