Ярлык радио-кнопки Angular и VoiceOver / ScreenReader

У меня есть радио-группа Angular Material mat. Когда я тестирую его с помощью Apple VoiceOver, он читает каждую метку радио как «[метка] и еще один элемент»

Например,

<mat-radio-button value="envelope">Envelope</mat-radio-button>

При фокусировке читается вслух как «Конверт и еще один предмет». Почему?

Вот весь набор:

<mat-radio-group aria-label="My Package Type" [(ngModel)]="myPackageType" class="radio-package-type mat-radio-small">
   <mat-radio-button value="box">Box</mat-radio-button>
   <mat-radio-button value="envelope">Envelope</mat-radio-button>
   <mat-radio-button value="irregular">Irregular</mat-radio-button>
</mat-radio-group>

Вот визуализированный HTML-код, скопированный из инструментов разработчика:

<mat-radio-group
  _ngcontent-gkg-c241=""
  role="radiogroup"
  aria-label="My Package Type"
  class="mat-radio-group radio-package-type mat-radio-small ng-pristine ng-valid is-value ng-touched"
  ng-reflect-model="box"
  ><mat-radio-button
    _ngcontent-gkg-c241=""
    value="box"
    class="mat-radio-button mat-accent mat-radio-checked"
    ng-reflect-value="box"
    tabindex="-1"
    id="mat-radio-2"
    ><label class="mat-radio-label" for="mat-radio-2-input"
      ><div class="mat-radio-container">
        <div class="mat-radio-outer-circle"></div>
        <div class="mat-radio-inner-circle"></div>
        <input
          type="radio"
          class="mat-radio-input cdk-visually-hidden"
          id="mat-radio-2-input"
          tabindex="0"
          name="mat-radio-group-0"
          value="box"
        />
        <div
          mat-ripple=""
          class="mat-ripple mat-radio-ripple mat-focus-indicator"
          ng-reflect-trigger="[object HTMLLabelElement]"
          ng-reflect-disabled="false"
          ng-reflect-centered="true"
          ng-reflect-radius="20"
          ng-reflect-animation="[object Object]"
        >
          <div class="mat-ripple-element mat-radio-persistent-ripple"></div>
        </div>
      </div>
      <div class="mat-radio-label-content">
        <span style="display: none;">&nbsp;</span>Box
      </div></label
    ></mat-radio-button
  ><mat-radio-button
    _ngcontent-gkg-c241=""
    value="envelope"
    class="mat-radio-button mat-accent"
    ng-reflect-value="envelope"
    tabindex="-1"
    id="mat-radio-3"
    ><label class="mat-radio-label" for="mat-radio-3-input"
      ><div class="mat-radio-container">
        <div class="mat-radio-outer-circle"></div>
        <div class="mat-radio-inner-circle"></div>
        <input
          type="radio"
          class="mat-radio-input cdk-visually-hidden"
          id="mat-radio-3-input"
          tabindex="0"
          name="mat-radio-group-0"
          value="envelope"
        />
        <div
          mat-ripple=""
          class="mat-ripple mat-radio-ripple mat-focus-indicator"
          ng-reflect-trigger="[object HTMLLabelElement]"
          ng-reflect-disabled="false"
          ng-reflect-centered="true"
          ng-reflect-radius="20"
          ng-reflect-animation="[object Object]"
        >
          <div class="mat-ripple-element mat-radio-persistent-ripple"></div>
        </div>
      </div>
      <div class="mat-radio-label-content">
        <span style="display: none;">&nbsp;</span>Envelope
      </div></label
    ></mat-radio-button
  ><mat-radio-button
    _ngcontent-gkg-c241=""
    value="irregular"
    class="mat-radio-button mat-accent"
    ng-reflect-value="irregular"
    tabindex="-1"
    id="mat-radio-4"
    ><label class="mat-radio-label" for="mat-radio-4-input"
      ><div class="mat-radio-container">
        <div class="mat-radio-outer-circle"></div>
        <div class="mat-radio-inner-circle"></div>
        <input
          type="radio"
          class="mat-radio-input cdk-visually-hidden"
          id="mat-radio-4-input"
          tabindex="0"
          name="mat-radio-group-0"
          value="irregular"
        />
        <div
          mat-ripple=""
          class="mat-ripple mat-radio-ripple mat-focus-indicator"
          ng-reflect-trigger="[object HTMLLabelElement]"
          ng-reflect-disabled="false"
          ng-reflect-centered="true"
          ng-reflect-radius="20"
          ng-reflect-animation="[object Object]"
        >
          <div class="mat-ripple-element mat-radio-persistent-ripple"></div>
        </div>
      </div>
      <div class="mat-radio-label-content">
        <span style="display: none;">&nbsp;</span>Irregular
      </div></label
    ></mat-radio-button
  ></mat-radio-group
>


person Steve    schedule 17.03.2020    source источник
comment
Можете ли вы вставить выведенный HTML-код в свой вопрос, выглядит нормально в вашем вопросе, но я подозреваю, что сгенерированная разметка не совсем правильная или в нее добавлены дополнительные элементы, которые вызывают такое поведение.   -  person Graham Ritchie    schedule 17.03.2020
comment
добавлен к вопросу   -  person Steve    schedule 17.03.2020
comment
Трудно сказать по беспорядку HTML, который он создает, но я заметил, что метка обернута вокруг всего, но также связана с for="mat-radio-3-input", это может вызвать странное поведение. Кроме того, поскольку этикетка обернута вокруг всего, причиной, вероятно, будет рябь, но мне нужно увидеть, как она меняется в зависимости от фокуса, проверки и т. Д. Извините за боль, но есть шанс превратить ее в скрипку, чтобы я мог проверить несколько вещей, немного поиграйте и вернитесь с большим, чем просто обоснованными предположениями.   -  person Graham Ritchie    schedule 18.03.2020


Ответы (1)


У меня была аналогичная проблема (macOS 10.15.3, Safari 13.0.5 и 10.15.4, 13.1, я не мог воспроизвести в Mac Chrome 80 или iOS 13.3.1 Safari). Похоже, что это происходит, когда <label> имеет дочерние элементы с display: block, особенно если есть либо сочетание дочерних элементов с display: block и без него, либо сочетание TextNodes и элементов с display:block.

В вашем случае метка является как неявной (входной элемент является дочерним элементом метки), так и явным (метка имеет атрибут, ссылающийся на идентификатор входа). Хотя это ненужное дублирование (как и добавление tagindex="0" к элементу <input>), оно не связано с проблемой. Я воспроизвел проблему с метками и входами только неявно и только явно. Похоже, для воспроизведения проблемы требуются две вещи:

  1. <label> изменен на display:block
  2. <label> имеет хотя бы один display:block дочерний элемент, но не все дочерние элементы с display:block

Изменение элемента метки таким образом, чтобы не выполнялось одно из этих двух требований, похоже, исправляет это.

<!-- VoiceOver is saying "First Nameandone more item, edit text" -->
<!-- implicit -->
<label style="display:block"> 
    <span style="display:block">First Name</span>
    <input type="text"> 
</label>

<!-- explicit -->
<div>
    <label for="firstname3" class="block"> 
        First Name
        <span style="display:block">Test</span>
    </label>
    <input id="firstname3" type="text">
</div>

person extra808    schedule 03.04.2020
comment
Фрагменты кода предназначены для демонстрации проблемы в Mac Safari без всей сложности примера в исходном вопросе. - person extra808; 03.04.2020