htmlangularprimeng

Is there a way to prevent a p-fieldset from autogenerating an aria-labelledby attribute?


I have an app with an angular front-end that uses several p-fieldset components.

The trouble I'm having is that these p-fieldset components keep generating 'Broken ARIA reference' errors.

The reason they do this is because the p-fieldset components auto-generate a child fieldset with child div with an autogenerated aria-labelledby attribute.

Doing an F12, this is the offending aria-labelledby attribute...

Which then results in a Broken ARIA reference when I do a WAVE scan.

enter image description here

I've tried setting this aria-labelledby attribute to empty in ngOnInit()

ngOnInit() {

  let pFieldSets = document.getElementsByTagName('p-fieldset');

  for (let ii=0; ii<pFieldSets.length; ii++) {

    let pFieldSet = pFieldSets[ii];

    let fieldSets = pFieldSet.getElementsByTagName('fieldset');

    for (let jj=0; jj<fieldSets.length; jj++) {
      let fieldSet = fieldSets[jj];

      let fieldsetChildren = fieldSet.children;
      for (let kk=0; kk<fieldsetChildren.length; kk++) {
        fieldsetChildren[kk].setAttribute('aria-labelledby','')
      }
    }
  }
}

The problem is this doesn't work because the ngOnInit() function is called before the div field with its auto-generated aria-labelledby attribute is created - and thus it just gets overridden.

And I've tried adding the value of the aria-labelledby attribute as an id to the p-fieldset in my html file like this...

<p-fieldset id="pn_id_43_header">

Which kind of works sometimes - but it's not reliable because the pn_id_43_header value can change.

Can anyone tell me how to either

  1. Permanently prevent the aria-labelledby attribute from being auto-generated?
  2. Set the aria-labelledby attribute to empty (like I do in the ngOnInit() function above) AFTER it is auto-generated so it doesn't just get overridden?

Thanks much!


Solution

  • at this moment, it's a bug (with pending PR fixing it): Fieldset: UniqueComponentId & aria-labelledBy #16694

    Running your code from ngOnInit or ngAfterViewInit won't help, because it changes attribute values on each toggle.

    So, you could add toggle listener and then run your code on collapsedChange emiter:

    <p-fieldset [toggleable]="true" (collapsedChange)="disableAria()">
    

    However, you should run it after a while to have effect, because it seems it sets values after the animation is done:

    disableAria() {
        // add some timeout
        setTimeout(() => {
          let pFieldSets = document.getElementsByTagName('p-fieldset');
         //...
         }, 500);
    

    Also, call it on first load, when rendering is done:

      ngAfterViewInit(){
        this.updateId();// or this.disableAria();
      }
    

    The problem is that it sets wrong id value, the rest is fine. So, another workaround would be to simply get the current id, and then replace all wrong numbers with that one in all children elements that have wrong referencing attribute values (with pn_id..something, which is admittedly a bit heavy work...):

    updateId() {
      //...
      const id = fieldSet.getAttribute('id');
    
      console.log('id', id);
    
      const allEls = Array.from(pFieldSet.querySelectorAll('*'));
      allEls.forEach((el: any) => {
        for (const attr of el.attributes) {
          if (attr.value.includes('pn_id')) {
            attr.value = attr.value.replace(/pn_id_\d+/, id);
          }
        }
    

    demo
    (set to updateId() version)