Search code examples
javascriptangulartabindex

How to get the tab focus on the first field when the tab is clicked using angular8


Hi i have totally 6 tabs, based on click of one tab the sub tabs opens. As soon as the subtab opens i want the focus to be on the first child of every tab. I tried by taking the id of first tab and trying to fetch the subtab id in that. For example: 1st tab is details_basic_info its sub tab contains tab-details_basic_info. So i tried to make details_basic_info to fetched and based on this by adding 'tab-' with the id of the dynamically fetched main tab on which it is clicked.But i failed to implement. can anyone help me out, how this can be done.

Thanks in advance.

DEMO: DEMO


Solution

  • If it were me I'd probably do something like this (although a bit less repetitive with the method handling but hey it's just a quick vanilla js proof of concept slapped together with bootstrap for example but can easily be ported to angular) so you don't care what the first focus-able element is as long it's supplied in the array that can be focused.

    Hope this helps, cheers!

    const focusableList = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
    
    focusFirstFocusableChildPoC = (id) => {
    
      const contentPane = document.getElementById(id);
    
      if (contentPane) {
      
          const focusableElements = contentPane.querySelectorAll(focusableList),
                firstFocusable = focusableElements[0];          
                // Typescript will want this to be <HTMLElement>focusableElements[0]; to cast.
    
          window.setTimeout(function () {
              // Kick this to the back of the line with the 'ol 0 timeout trick.
              firstFocusable ? firstFocusable.focus() : notifyOfFailure();
          }, 0); 
          
    
      } else {
         notifyOfFailure(); 
      }
    }
    
    notifyOfFailure = () => {
      alert('NO FOCUS FOR YOU!');
    }
    .tab-content {
      padding: 2rem;
    }
    
    .tab-content *:focus {
      outline: red 3px dotted;
    }
    
    .tab-content *:focus:after {
      content: '*';
      margin-top: 1rem;
      color: red;
    }
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    
    
    <ul class="nav nav-tabs" id="myTab" role="tablist">
      <li class="nav-item">
        <a class="nav-link active" data-toggle="tab" href="#panel1" role="tab" onclick="focusFirstFocusableChildPoC('panel1')">Home</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" data-toggle="tab" href="#panel2" role="tab" onclick="focusFirstFocusableChildPoC('panel2')">Profile</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" data-toggle="tab" href="#panel3" role="tab" onclick="focusFirstFocusableChildPoC('panel3')">Contact</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" data-toggle="tab" href="#panel4" role="tab" onclick="focusFirstFocusableChildPoC('panel4')">Contact</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" data-toggle="tab" href="#panel5" role="tab" onclick="focusFirstFocusableChildPoC('panel5')">Contact</a>
      </li>
    </ul>
    
    <div class="tab-content" id="myTabContent">
      <div class="tab-pane show active" id="panel1" role="tabpanel">
        <input placeholder="a text input" type="text">
        <button>A Button</button>
        <input type="checkbox">
        <input type="number">
      </div>
      <div class="tab-pane" id="panel2" role="tabpanel">
        <label><input type="checkbox"> Focus testing</label>
        <input type="text">
        <button>A Button</button>
        <input type="number">
      </div>
      <div class="tab-pane" id="panel3" role="tabpanel">
        <button>A Button</button>
        <input type="text">
        <input type="checkbox">
        <input type="number">
      </div>
      <div class="tab-pane" id="panel4" role="tabpanel">
        <a href="#">Test Anchor Link</a>
        <button>A Button</button>
        <input type="text">
        <input type="checkbox">
        <input type="number">
      </div>
      <div class="tab-pane" id="panel5" role="tabpanel">
        Nothing here to focus bro...
      </div>
    </div>