I've been building a to-do list web app as part of The Odin Project's JavaScript course. The user actions are basic: add and delete tasks and projects, as well as edit tasks. But in coding a way for a user to edit a task, I came across a problem.
When a task card is clicked in the app, a full-screen pop-up with a form appears where a user can edit that specific task's details (i.e., name, description, project, priority, and due date). So, all that task's currently selected info should be presented as editable content within the form, or as placeholder values in the inputs.
While giving placeholders to the first four of these inputs is fairly straightforward—using a placeholder
attribute on the first two type="text"
inputs and setting the selected
attribute on the last two option
inputs to true
for the correct option—I couldn't figure out a way to display the task's previously selected due date as a placeholder on a type="date"
input. Instead, the default mm/dd/yyyy
remained as the "placeholder" for my date input, even if I gave this input a placeholder
attribute with a value.
Off to Google I went, quickly discovering this is a known problem and coming across this Stack Overflow threadand this GeeksforGeeks article.
Solution 1: CSS's ::before
pseudo-element
The top-voted comment in the SO thread suggests using the ::before pseudo-element in CSS to create a placeholder before the mm/dd/yyyy
default, but that still appears as if its within the date input field.
<input type="date" placeholder="Choose a Date" />
input[type="date"]:before {
content: attr(placeholder) !important;
color: #aaa;
margin-right: 0.5em;
}
input[type="date"]:focus:before,
input[type="date"]:valid:before {
content: "";
}
When the input field is selected, the placeholder goes away and a user is just left with the option to select a date.
While this seems to be a fine method (although it doesn't appear to work on Firefox) in certain situations, it isn't what I was looking for. I needed the input to display just task's current date as a placeholder, not also the default mm/dd/yyyy
.
Solution 2: The onfocus
attribute
The GeeksforGeeks article and the second top-rated SO comment recommend an alternate approach: writing the input as a standard type='text'
input and giving it the placeholder value you want. Then, using the onfocus
attribute, the input can (ideally) change to type='date'
input, like so:
<input type="date" placeholder="01/01/2001" onfocus="(this.type='date')">
Unfortunately, to reasons unknown to me I couldn't get this to work. I tested it in multiple browsers, and still got nothing.
So, I chose to figure out a different method to give my date input a placeholder.
Solution 3: A button and an event listener
The approach I came up with, while perhaps not the cleanest solution, works fine for what I needed.
My code is pasted below as well as here in a CodePen if you want to play around with it on your own.
<button id="date-input-btn">01/01/2001</button>
#date-input-btn, #date-input {
outline: none;
border: none;
font-family: Helvetica;
font-size: 16px;
border-radius: 4px;
font-weight: 500;
background-color: lightgray;
color: gray;
}
#date-input-btn {
padding: 5px 6px;
text-align: left;
}
#date-input {
padding: 4px 6px;
}
function switchToDateInput() {
document.getElementById('date-input-btn').remove();
const dateInput = document.createElement('input');
dateInput.type = 'date';
dateInput.id = 'date-input';
document.body.appendChild(dateInput);
}
const dateInputBtn = document.getElementById('date-input-btn');
dateInputBtn.addEventListener('click', switchToDateInput);
}
The code in my to-do list project is slightly more complicated, as I am creating all the DOM elements with JS and appending the button and input to a different div
container element, but the idea is the same as in the code above.
What's going on here?
In my HTML file I have a button
element with an id
of #date-input-btn
. The text inside this button simulates the placeholder value for my date input.
In the JS file, I have an event listener on the button that, when clicked, triggers a function called switchToDateInput()
. All this function does is remove the button that was clicked and append a date input to the DOM in its place, giving the appearance that the button "transformed" into a date input when clicked.
Finally, if we just style both our button and date input the same, we get a simulated placeholder value for a date input!
Note: I added one extra pixel to the top and bottom padding on the button. In my case this made the button appear as the same height as the date input that takes its place.
Here's the final result from my CodePen using the code above:
Before click:
After click:
One downside of this approach is that a user has to click twice—once to fire the event listener on the button and a second time to bring up the date input selector.
If you're curious, here's what this looks like in my to-do list project:
Before click:
After click:
Conclusion
I hope this helps if you've encountered this same problem of wanting to give a date input a "pre-selected" date as a placeholder. If you know of a more elegant solution (or if you figure out what I did wrong with solution 2), I'd love to hear it.
Thanks for reading and carry on coding.
Top comments (1)
That works for me (i use react, but it doesnt matter):