Test Vue 2.0 Focus
Incorrectly functional vue test page that inserts rows at top and focuses on Date field - the 1st row fails while adding 2 thru n rows works fine
by barbedCoil
HTML
<!DOCTYPE html>
<!--
This is a snippet of the much larger page in production so you may see things here
that make you wonder why? That's not the point.
The point is that I can click add, a new row is inserted at the top of the backing data
array and the cursor is NOT focused on the Date field for the 1st new row BUT adding
subsequent rows it works fine
Here is the error displayed in the console on adding first row:
vue.min.js:6 TypeError: Cannot read property 'focus' of null
at pt.tipEntries (test_vue2.js:72)
at So.run (vue.min.js:7)
at $e (vue.min.js:6)
at Array.<anonymous> (vue.min.js:7)
at e (vue.min.js:7)
at <anonymous>
-->
<body>
<div id="appView" class="container-fluid" v-cloak>
<h3>Vue.js 2.x Add Rows Focus - This does NOT work on 1st row</h3>
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
<!-- this is used in many other places in the production page hence it's location -->
<datalist id="listJobCodesALL">
<option v-for="jobCode in jobCodes" v-bind:value="jobCode.job_code" v-text="jobCode.job"></option>
</datalist>
<div class="table-tips">
<div>
<button v-on:click="onAddTipEntry(90125, 101)" class="btn btn-sm btn-primary">
<span>Add</span>
</button>
</div>
<br/>
<table id="tableTips" class="table table-bordered table-condensed table-responsive">
<thead>
<tr class="thead-block">
<th class="row_num-hdr">Row</th>
<th class="delete_tip-hdr">Delete</th>
<th class="business_date-hdr">Date</th>
<th class="job_code-hdr">Code</th>
...
CSS
body {
padding-top: 1px;
padding-bottom: 1px;
}
/* Set padding to keep content from hitting the edges */
.body-content {
padding-left: 15px;
padding-right: 15px;
}
/* Override the default bootstrap behavior where horizontal description lists
will truncate terms that are too long to fit in the left column
*/
.dl-horizontal dt {
white-space: normal;
}
/* Set width on the form input elements since they're 100% wide by default */
input,
textarea
{
max-width: 240px !important;
margin-left: 15px;
}
select
{
max-width: 280px !important;
margin-left: 15px;
cursor: pointer;
}
.selected-command
{
color: #0288D1 !important;
font-weight: bold;
}
/* B O O T S T R A P */
/* fixes animation issues - mostly on mobile */
.collapsing
{
-webkit-transition: none;
transition: none;
}
.fa-trash,
.glyphicon-trash
{
color: maroon;
}
a.hover:hover
{
font-weight: bolder;
}
/* V U E */
[v-cloak]
{
display: none;
}
/* C O M M O N */
input[type=checkbox].format-checkbox
{
text-align: left;
height: 20px;
width: 20px;
cursor: pointer;
}
.el_hide
{
display: none;
}
.el_show
{
display: normal;
}
.el_center
{
margin: 0 auto;
}
.el_maroon
{
color: maroon;
}
.el_blue
{
color: #337ab7;
}
/* scroll container - NOTE: set height: ###px; on dom element otherwise scroll does not work */
.box
{
border: 1px solid lightgray;
border-radius: 2px;
overflow-y: scroll;
overflow-x: hidden;
}
.tbody-block
{
display: block;
height: 133px;
overflow-x: hidden;
overflow-y: visible;
}
.thead-block
{
display:block;
}
td {
padding: 0;
}
.row_num-hdr
{
width: 45px !important;
min-width: 45px !important;
max-width: 45px !important;
}
.business_date-hdr
{
width: 136px !important;
min-width: 136px !important;
max-width: 136px !important;
}
.job_code-hdr
{
width: 60px !important;
min-width: 60px !important;
max-width: 60px !important;
}
.row_num
{
width: 34px;
text-align:...
JavaScript
"use strict";
/*
This script uses vue.js 1.x - This script and the associated
html page functions as needed:
- User Clicks Add button
- onAddTipEntry(..) is called which clones tipEntry below
- Cloned tip entry is updated with basic data
- Cloned tip entry is added to tipEntries data array by splice
NOTE: I need new rows to be added to top so user can add new entries
in a very fast and efficient way.
*/
// we have several "namespaces" under HS
var HS = HS || {};
HS.Main = {};
HS.Main =
{
vm: new Vue({
el: "#appView",
data:
{
businessDate: null,
jobCodes:
[
{ job: "100", job_code: "100 - Job 1" },
{ job: "101", job_code: "101 - Job 2" },
{ job: "102", job_code: "102 - Job 3" },
{ job: "103", job_code: "103 - Job 4" },
{ job: "104", job_code: "104 - Job 5" },
{ job: "105", job_code: "105 - Job 6" },
],
tipEntries: [],
tipEntry:
{
row_num: 0,
person_id: null,
tip_date: null,
job_code: "",
status_code: 0,
delete_flag: false
},
tipAddNew: false,
status:
{
base_code: 0,
change_code: 1,
new_code: 2,
delete_code: 3
}
},
watch:
{
// we just watch to see when new entry by user
"tipEntries": function (val, oldVal)
{
if (this.tipAddNew === false) return;
// no error side effect even if fails
//$("#tip-0").focus();
// uncomment this to see the vue error
document.getElementById("tip-0").focus();
HS.Main.vm.tipAddNew = false;
...