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.
Which then results in a Broken ARIA reference when I do a WAVE scan.
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
Thanks much!
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)