How can I automatically bind amp state (from remote source)? - html

My amp page has a state as follows:
<amp-state id="remoteData" src="https://remoteDataurl.com">
<script type="application/json">
{
"name": "Foo",
"email": "foo#bar.com"
}
</script>
</amp-state>
I would like to bind the response to an element in the page:
<p [text]="'Hello ' + remoteData.name"> ... </p>
<p [text]="'Your email is ' + remoteData.email"> ... </p>
The text is actually already bound, but it will not refresh until an event occurs on the page.
How can I get it to refresh the state automatically?

I believe <amp-state> does not give you this functionality.
My solution for now is to use <amp-list> with the following attributes.
<amp-list
layout="fixed-height"
height="80"
src="https://remoteDataurl.com"
single-item
items="."
>
<template type="amp-mustache">
<p> Hello {{ name }} </p>
<p> Your email is {{ email }} </p>
</template>
</amp-list>

You can do it that way.
<amp-state
id = "product"
src="https://www.alectrico.cl/listas/designer&productos.json">
</amp-state>
The state "product" now it's linked to some url from outside.

Related

Accessing submit button which is created for every item in a loop -- HTML jQuery AJAX

I have a wishlist page which contains items each having a remove button which is created in a loop using form and each button has item id as value. I want to make a post request whenever a remove button is clicked in order to remove that item from the database.
But the problem is that there are many buttons created in the loop with the same id, so how do I access them individually?
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<h1>::WISHLIST::</h1>
{% for wish in wishes %}
<img src={{wish.image_path}} width="150" height="200">
</br>
{{wish.material}}
{{wish.productType}}
</br>
{{wish.price}}
</br>
<form method="POST" target="_self">
<button id="remove_wish" name="remove_wish" type="submit" value={{wish.id}}>Remove</button>
</form>
</br>
{% endfor %}
<script>
$(document).ready(function() {
$('#remove_wish').click(function (event) {
event.preventDefault();
alert($('#remove_wish').val())
$.ajax({
data : {
delete_wish : $('#remove_wish').val()
},
type : 'POST',
url : '/wishlist/',
success: function (data) {
location.reload();
},
error: function (e) {
alert('something went wrong')
}
});
});
})
</script>
</body>
</html>
Here I tried using the same id, but this only works for the top most item on the wishlist and for others it gives the error: NoResultFound: No row was found for one()
You shouldn't have more than one element in the DOM with the same id.
Change in your button the next things:
Add a class to the buttons. Let's say remove_wish.
Change the id value of the buttons to wish-{{wish.id}} (for example).
<button class="remove_wish" id="wish-{{wish.id}}" name="remove_wish" type="submit" value={{wish.id}}>Remove</button>
In your AJAX call, change the selector of the event for listening to the class selector instead of the id selector:
$('.remove_wish')
Get the id of your element using the substring function:
var id = $(this).attr('id');
var id_value = id.substring(5); //five because "wish-" has five characters.
I think this should do the work.
I have a couple of alternatives of how could you solve your issue and a tip.
TIP:
Remove the <form> tag from your foreach, otherwise you'll be creating one form per button. The ideal scenario would be having only one form and several buttons. Like this:
<form method="POST" target="_self">
{% for wish in wishes %}
<img src={{wish.image_path}} width="150" height="200">
</br>
{{wish.material}}
{{wish.productType}}
</br>
{{wish.price}}
</br>
<button id="remove_wish" name="remove_wish" type="submit" value={{wish.id}}>Remove</button>
</br>
{% endfor %}
</form>
ALTERNARTIVE #1 :
As #cooper and #Shree already told you, you should get rid of the id and use a class instead. Now, wrap your button inside a container, a div (it could be with an id or with a class) for example (please notice that this container must be outside of your foreach as well). And change the type of your button from submit to button. Like this:
<form method="POST" target="_self">
<div id="divContainer">
{% for wish in wishes %}
<img src={{wish.image_path}} width="150" height="200">
</br>
{{wish.material}}
{{wish.productType}}
</br>
{{wish.price}}
</br>
<button class="remove_wish" type="button" data-wishid={{wish.id}} >Remove</button>
</br>
{% endfor %}
</div>
</form>
//and then you can manage all your buttons click events like this
$("#divContainer").on("click", "remove_wish", function() {
var id = $(this).data('wishid');
//the rest of your code
});
ALTERNARTIVE #2 :
Or even easier, you can use the onclick event and pass your id to a function. Like this:
<form method="POST" target="_self">
{% for wish in wishes %}
<img src={{wish.image_path}} width="150" height="200">
</br>
{{wish.material}}
{{wish.productType}}
</br>
{{wish.price}}
</br>
<button type="button" onclick="removeWish(" + {{wish.id}} +")" >Remove</button>
</br>
{% endfor %}
</form>
//and outside your $(document).ready(function()
function removeWish(id) {
//the rest of your code
}

Locales/literals containing html

In
locale/lang.json I have
{
"title": "Title",
"image": "service-corporate_thumb-v2.jpg",
"alt": "alt",
"imageFooter": "Some caption %",
"imageFooterCTA": "author",
"imageFooterURL": "https://example.com/author",
},
I'm trying to generate the author like, like so:
<img :src="require(`~/assets/img/services/${service.image}`)" :alt="service.alt" class="mb-8">
<p>{{ service.imageFooter.replace('%', `${service.imageFooterCTA}`) }}</p>
But this prints out in the generated HTML:
{{ service.imageFooter.replace('%', `${service.imageFooterCTA}`) }}
How can I generate html inside the {{ expresion }} ?
You need to use v-html for generating html in a template.
More info here.
For your example try this
<p class="mb-8">
<a v-html="service.imageFooter.replace('%', '$' + service.imageFooterCTA + '')">
</p>
Notes:
the tag that has a v-html directive will be replaced, so you could use anything, not only a
the value for v-html needs to be valid JS code that will be executed in the current context. This the reason I treated the tag inside as a string and removed the interpolation {.

amp-html: Use query param in amp-list src

I have an amp page that is called on:
https://expample.amp.com?id=1234abc
(Not the real url.)
<amp-list src="https://some.external-url.com/?dataid=NEEDS_ID"
layout="responsive"
items="Result"
width="100"
height="100"
>
<template type="amp-mustache">
<p>{{FullName}}</p>
</template>
</amp-list>
I want my id query param to be injected into the src of the amp-list tag at NEEDS_ID.
I already checked the QUERY_PARAM docs but couldn't understand what exactly I'm supposed to do.
I've already tried src="https://some.external-url.com/?dataid=QUERY_PARAM(id)" but that didn't work.
Any pointers/references?
My silly-and-dumb solution to this was writing an EJS node server, that parses a <%= query.id %> in that url and then sends that page to the client. Is that the correct way to do it?
I do strongly suppose that the call to the Url independent to the AMP Page, results in valid json data.
If this is the case, you may face following problems:
CORS
your result data is somehow corrputed
As for me, this saved me a lot of time:
public function getData(){
echo header('Access-Control-Allow-Origin: https://amp-YOUR-SITE');
echo header('Access-Control-Allow-Credentials: true');
echo json_data;
}
https://expample.amp.com?slug=1234abc
<amp-list id="time"
layout="fixed-height"
height="18"
src="https://api.exemple.com/posts?slug=QUERY_PARAM(slug)"
binding="refresh"
data-amp-replace="QUERY_PARAM"
single-item
items=".">
<template type="amp-mustache">
<p>{{title}}</p>
<p>{{content}}</p>
</template>
</amp-list>

amp-list not printing returned data from the connected JSON file

I'm trying to implement amp-list to allow a different currency depending on where the user is from. I've implemented the amp-list element and created a JSON file (which is a CORS url), containing the data using the correct syntax.
The amp-list however is not printing the data, and instead printing a blank space. The HTML template is:
<amp-list width="auto"
height="50"
layout="fixed-height"
src="/amp-price/57938">
<template type="amp-mustache">
<p class="price align-center {{test}}">{{price}}</p>
</template>
</amp-list>
And the JSON response is:
{"items": [{"price": "\u00a321.59", "test": "test"}]}
But the rendered HTML is:
<amp-list width="auto" height="50" layout="fixed-height" src="/amp-price/57938" class="i-amphtml-element i-amphtml-layout-fixed-height i-amphtml-layout-size-defined i-amphtml-layout" aria-live="polite" style="height: 50px;">
<template type="amp-mustache">
<p class="price"> - </p>
</template>
<div class="i-amphtml-fill-content i-amphtml-replaced-content" role="list"></div></amp-list>
The JSON response has all the correct AMP headers, and I'm not getting any AMP errors in the console.
I've also followed the src link in the page source and it goes to the correct URL.
Is there something simple I'm missing?
I had the same problem and I tried almost everything. The amp-list in safari 10 doesn't load the json endpoint.
But the solution for me is to add credentials="include" into my amp-list tag:
the final amp-list:
<amp-list credentials="include" id="smallcartsList" width="auto" height="#HeightRequest" [height]="CurrentCartList.items.length == 0 ? 5 : 50 * CurrentCartList.items.length" media="(max-width: 1199px)" layout="fixed-height" binding="no" src="/API/CartList/GetCartsList" [src]="cartlistsource" template="cartlistdetail"> </amp-list>
Sebastian Benz is correct I have use the same code and working fine
Here is working url
HEAD JS
<script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.1.js"></script>
BODY HTML
<amp-list width="auto"
height="50"
layout="fixed-height"
src="https://jsonblob.com/api/jsonBlob/1f6f838d-25aa-11e8-8863-d99090d9ec78">
<template type="amp-mustache">
<p class="price align-center {{test}}">{{price}}</p>
</template>
</amp-list>
JSON DATA LINK

Update amp-list data source without form

I have an amp-list and I want to update its src dynamically without using form, just using a bunch of button divs that use data from amp-state that changes on tap on an element.
For example, tapping #elementOne will change product.currentIndex to 1, so list's [src] will change to 'localhost/example/data?page=' + product.currentIndex = 'localhost/example/data?page=1', hence the amp-list will be updated after src change.
Here's what I've tried so far:
<amp-state id="product">
<script type="application/json">
{
"page": 0
}
</script>
</amp-state>
<amp-state id="productState"
[src]="'localhost/example/data?page=' + product.page"
src="localhost/example/data?page=0"></amp-state>
<div role="button" tabindex="0" on="tap:AMP.setState({product: {page: 1 }})">
<span>Page One</span>
</div>
<div role="button" tabindex="0" on="tap:AMP.setState({product: {page: 2 }})">
<span>Page Two</span>
</div>
<amp-list width="auto" height="1024" layout="fixed-height"
src="localhost/example/data" [src]="productState.items">
<template id="product-item-template">
<!-- A template -->
</template>
</amp-list>
Is there a way to do this without using form?
Just simply bind the src attribute of the amp-list to the calculated url string, like this:
[src]="'/example/data/?page=' + product.page"
Your markup should look like this:
<amp-list width="auto" height="1024" layout="fixed-height"
src="localhost/example/data" [src]="'/example/data/?page=' + product.page">
<template id="product-item-template">
<!-- A template -->
</template></amp-list>