Search code examples
javascripthtmlamp-html

Amp-state getting ignored until setState() fired


I'm building amp page that should show different download url based on countries. I'm able to show/hide proper <a> element by css via adding isEU group to <amp-geo> config. But what I want is only one link on the page with variable href. I'm trying to achieve this by using but I'm unable to use <amp-state> though it is generated properly.

Even examples from amp documentation doesn't work until I tap on the <button on="tap:AMP.setState({foo: 'amp-bind'})">Say "Hello amp-bind"</button>. Then it triggers calculations and page shows all values. Before that no values interpolated/calculated.

What am I doing wrong here?

enter image description here

<!doctype html>
<html ⚡>

<head>
    <meta charset="utf-8">
    <title>TESTPAGE</title>
    <meta name="viewport"
          content="width=device-width,minimum-scale=1,initial-scale=1">
    <script async
            src="https://cdn.ampproject.org/v0.js"></script>
    <script async
            custom-element="amp-geo"
            src="https://cdn.ampproject.org/v0/amp-geo-0.1.js"></script>
    <script async
            custom-element="amp-bind"
            src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
    <style>
        [class*=-only] {
            display: none;
        }

        .amp-geo-group-isEU .eu-only {
            display: block;
        }

        body:not(.amp-geo-group-isEU) .non-eu-only {
            display: block;
        }
    </style>
</head>

<body class="amp-geo-pending">
    <amp-state id="stateTest"
               class="i-amphtml-element i-amphtml-layout-container"
               i-amphtml-layout="container"
               hidden=""
               aria-hidden="true">
        <script type="application/json">
            {
                "testInitialKey": "initial state value"
            }
        </script>
    </amp-state>
    <amp-state id="myCircle"
               class="i-amphtml-element i-amphtml-layout-container"
               i-amphtml-layout="container"
               hidden=""
               aria-hidden="true">
        <script type="application/json">
            {
                "radius": "4"
            }
        </script>
    </amp-state>
    <amp-geo layout="nodisplay">
        <script type="application/json">
            {
              "AmpBind": true,
              "ISOCountryGroups": {
                "isEU": ["at", "be", "bg", "bs", "ch", "cy", "cz", "de", "dk", "ee", "es", "fi", "fr", "gb", "gr", "hr", "hu", "ie", "is", "it", "li", "lt", "lu", "lv", "mt", "nl", "no", "pl", "pt", "ro", "se", "si", "sk"]
              }
            }
        </script>
    </amp-geo>
    <h1 [class]="ampGeo.isEU ? 'isEU' : 'nonEU'"
        [text]="'isEU: ' + (ampGeo.isEU ? 'true' : 'false').toUpperCase()"></h1>
    <h2 [text]="stateTest.testInitialKey"></h2>
    <a class="eu-only"
       [href]="'http://google.com/' + ampGeo.ISOCountry == 'cy' ? 'cyprusLink' : 'defaultLink'">LINK_CY</a>
    <a class="non-eu-only"
       href="http://google.com/?frenchLink">LINK_FR</a>
    <hr>
    <amp-bind-macro id="circleArea"
                    arguments="radius"
                    expression="3.14 * radius * radius"></amp-bind-macro>

    <div>
        The circle has an area of <span [text]="circleArea(myCircle.radius)">0</span>.
    </div>
    <hr>
    <p [text]="'Hello ' + foo">Hello World</p>
    <button on="tap:AMP.setState({foo: 'amp-bind'})">Say "Hello amp-bind"</button>
</body>

</html>


Solution

  • If I understand correctly, the problem you are facing is amp-bind's are only computed on user action. You have to initialize the initial value server side. That is how bind works. The idea is to ensure page speed and no need to run JavaScript when page is loaded.

    It is very common to see code like

    <div class="foo" [class]="x ? 'foo' : 'bar'">
    

    That is, initialize the class attribute server side, but then dynamically update it upon user interaction which may result in state change.

    However, I can see the problem this creates with AMP Geo. Is the server supposed to replicate that functionality to pre initialize the value? See https://github.com/ampproject/amphtml/issues/14637 for example. Sounds like the same problem you are facing. You might like to add a comment there to provide feedback as to why you would like some kind of support added.