1

I have an amp-form with several radio buttons. Depending on the radio button selected I would like to disable or enable an input field. The input field is disabled by default.

Given that the input includes the disabled attribute the field is always disabled. I have tried setting disabled="disabled" and then changing it to disable="enabled" but the doesn't work due to the presence of the disabled attribute.

     [disabled]="formFeedBack.hoursEnable" disabled="disabled"

where I use on="change:Amp.setState... to change the value hoursEnabled to either "enabled" or "disabled".

Within the constraints of AMP how can one toggle between the disabled and enabled states?

blindChicken
  • 352
  • 4
  • 13

3 Answers3

4

AMP does support removing or adding boolean attributes.

Boolean expression results toggle boolean attributes. For example: . When expr evaluates to true, the element has the controls attribute. When expr evaluates to false, the controls attribute is removed.

This works:

<form on="valid:AMP.setState({disable: false});>
<input type="submit" disabled [disabled]="disable" value="Go"/>

See in action here https://codepen.io/vercer/pen/vWEmNG

Dev Vercer
  • 166
  • 1
  • 7
3

Unfortunately, adding/removing attributes is not possible in AMP yet. The bind documentation does state that you can use [disabled] but I believe it's W3C Specification that any browser that detects presence of disabled attribute will treat the field disabled.

However, you could do something like following to mimic disabled field.

.hide {
  display: none;
}
<script async src="https://cdn.ampproject.org/v0.js"></script>
    <script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>
    <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
        
    <form method="post" action-xhr="#">
          <label><input type="radio" name="fields" on="change:AMP.setState({disableFirst: event.value, disableSecond: event.value ? false : true})"> Disable 1st Field</label><br>
        <label><input type="radio" name="fields" on="change:AMP.setState({disableSecond: event.value, disableFirst: event.value ? false : true})"> Disable 2nd Field</label><br>
        <label>First Field</label>
        <input [class]="disableFirst ? 'hide' : ''" type="text" name="firstField" [value]="firstFieldValue" on="input-debounced:AMP.setState({firstFieldValue: event.value})" />
        <input class="hide" [class]="disableFirst ? '' : 'hide'" type="text" name="fakeFirstField" [value]="firstFieldValue" disabled="disabled" />
<br>
        <label>Second Field</label>
        <input [class]="disableSecond ? 'hide' : ''" type="text" name="secondField" [value]="secondFieldValue" on="input-debounced:AMP.setState({secondFieldValue: event.value})" />
        <input class="hide" [class]="disableSecond ? '' : 'hide'" type="text" name="fakeSecondField" [value]="secondFieldValue" disabled="disabled" />
    </form>
adnanyousafch
  • 1,172
  • 9
  • 26
  • This is a very good idea, but it causes some complications in that the value entered in one field, that then gets toggled will still be submitted with the form. This can be handled server side. Fortunately I found a simpler work-around that better fits my use case. My inputs are type=number, so I set min and max to 0, when it should be disabled and then to the correct value when enabled. HTML validation prevents the form from being submitted if the value entered is wrong. – blindChicken Oct 28 '17 at 01:18
2

You can also work around this by using amp-list. The benefit being that you'll have one field with a name that would match your object binding on submit.

amp-list needs a valid src json. If you point it to a valid json formatted like so then the input box will show when the page first loads:

{
  "items": [ { "disabled": "enabled" } ]
}

<script src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.1.js"></script>
<script async src="https://cdn.ampproject.org/v0.js"></script>

    <amp-state id="inputState">
        <script type="application/json">
            {
                "items" : [ { "disabled": "enabled" } ],
                "city" : ""
            }
        </script>
    </amp-state>

      <input type="radio" value="1" name="rb" id="rb1" class="relative" checked on="change:AMP.setState({inputState:{disabled:'enabled'}})" />
      <label for="rb1" class="" aria-hidden="true">Enable City Box</label>
      <input type="radio" value="2" name="rb" id="rb2" class="relative" on="change:AMP.setState({inputState:{disabled:'disabled'}})" />
      <label for="rb2" class="" aria-hidden="true">Disable City Box</label>
      <amp-list width="auto" height="25" src="https://myserver/stuff/itemsEnabled.json" [src]="inputState">
          <template type="amp-mustache">
              <label for="q">City</label>
              <input id="q" name="q" placeholder="City" type="text" {{disabled}}="{{disabled}}" value="{{city}}" on="change:AMP.setState({inputState:{city:event.value}})" />
          </template>
      </amp-list>
      <input id="x" name="x" placeholder="Country" type="text" />
      <input type="submit" />
Ryan Vettese
  • 514
  • 9
  • 22
  • 1
    This solution causes an amp validation error because amp-mustache cannot be used to add attributes to tags. [link](https://www.ampproject.org/docs/reference/components/amp-mustache#restrictions) – blindChicken Oct 28 '17 at 01:30