{"id":1671,"date":"2024-08-02T11:02:51","date_gmt":"2024-08-02T09:02:51","guid":{"rendered":"https:\/\/blog.sutilweb.eu\/?page_id=1671"},"modified":"2024-08-02T11:02:52","modified_gmt":"2024-08-02T09:02:52","slug":"007-renderizado-dinamico","status":"publish","type":"page","link":"https:\/\/sutilweb.eu\/index.php\/lenguajes\/javascript\/javascript-practico\/18-single-page-application-spa\/007-renderizado-dinamico\/","title":{"rendered":"007. Renderizado Din\u00e1mico"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">En el cap\u00edtulo anterior hab\u00edamos terminado de maquetar y programar la <strong>cabecera<\/strong> de nuestra <strong>SPA<\/strong>. En este cap\u00edtulo vamos a programar la parte que va fuera de la <strong>cabecera<\/strong>, que es donde vamos a tener los <strong>posts<\/strong> que traeremos del sitio <strong>WordPress<\/strong> sobre el que estemos consumiendo los datos.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p class=\"wp-block-paragraph\">Crearemos un archivo denominado <em>Posts.js<\/em>, dentro de la carpeta <em>components<\/em> que traer\u00e1 todos los posts. Se trata de un <strong>componente funcional<\/strong>, de <strong>presentaci\u00f3n<\/strong>, es por ello que lo incluimos en dicha carpeta, y no en la de <em>helpers<\/em>. Vamos a mandar a llamar al archivo <em>posts.js<\/em> en el archivo <em>App.js<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tambi\u00e9n vamos a trabajar con el <strong>componente <\/strong><em>PostCard.js<\/em> que creamos en el cap\u00edtulo anterior, y que va a cobrar protagonismo en este cap\u00edtulo. Dicho archivo nos va a permitir imprimir una tarjeta por cada post que traigamos. Esta PostCard se va a generar en el <strong>DOM<\/strong> por cada post que haya recibido la petici\u00f3n. La sintaxis de nuestro archivo <em>PostCard.js<\/em> va a tener el siguiente c\u00f3digo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sintaxis de <em>PostCard.js<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">export function PostCard(props) {\n&nbsp; let { date, slug, title, _embedded } = props;\n&nbsp; let dateFormat = new Date(date).toLocaleDateString(),\n&nbsp; &nbsp; urlPoster = _embedded[\"wp:featuredmedia\"]\n&nbsp; &nbsp; &nbsp; ? _embedded[\"wp:featuredmedia\"][0].source_url\n&nbsp; &nbsp; &nbsp; : \"app\/assets\/favicon.png\";\n\n&nbsp; return `\n&nbsp; &nbsp; &nbsp; &nbsp; &lt;article class=\"post-card\"&gt;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;img src=\"${urlPoster}\" alt=\"${title.rendered}\" \/&gt;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;h2&gt;${title.rendered}&lt;\/h2&gt;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;p&gt;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;time datetime=\"${dateFormat}\"&gt;${dateFormat}&lt;\/time&gt;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;a href=\"#\/${slug}\"&gt;Ver publicaci\u00f3n&lt;\/a&gt;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;\/p&gt;\n&nbsp; &nbsp; &nbsp; &nbsp; &lt;\/article&gt;\n&nbsp; &nbsp; `;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">La sintaxis de nuestro archivo <em>Posts.js<\/em> ser\u00eda el siguiente.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">export function Posts() {\n&nbsp; const $posts = document.createElement(\"section\");\n&nbsp; $posts.id = \"posts\";\n  $posts.classList.add(\"grid-fluid\");\n\n&nbsp; return $posts;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Asimismo hemos tenido que modificar el archivo <em>App.js<\/em>, que queda con la siguiente sintaxis.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">import api from \".\/helpers\/wp-api.js\";\nimport { ajax } from \".\/helpers\/ajax.js\";\nimport { Header } from \".\/components\/Header.js\";\nimport { Loader } from \".\/components\/Loader.js\";\nimport { Posts } from \".\/components\/Posts.js\";\nimport { PostCard } from \".\/components\/PostCard.js\";\n\nexport function App() {\n&nbsp; const d = document,\n&nbsp; &nbsp; $root = d.getElementById(\"root\");\n\n&nbsp; $root.appendChild(Header());\n&nbsp; $root.appendChild(Posts());\n&nbsp; $root.appendChild(Loader());\n\n&nbsp; ajax({\n&nbsp; &nbsp; url: api.POSTS,\n&nbsp; &nbsp; cbSuccess: (posts) =&gt; {\n&nbsp; &nbsp; &nbsp; console.log(posts);\n&nbsp; &nbsp; &nbsp; let html = \"\";\n&nbsp; &nbsp; &nbsp; posts.forEach((post) =&gt; {\n&nbsp; &nbsp; &nbsp; &nbsp; html += PostCard(post);\n&nbsp; &nbsp; &nbsp; });\n&nbsp; &nbsp; &nbsp; d.querySelector(\".loader\").style.display = \"none\";\n&nbsp; &nbsp; &nbsp; d.getElementById(\"posts\").innerHTML = html;\n&nbsp; &nbsp; },\n&nbsp; });\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Tambi\u00e9n vamos a modificar el archivo <em>style.css<\/em>, que quedar\u00eda como sigue.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">html {\n&nbsp; box-sizing: border-box;\n&nbsp; font-family: sans-serif;\n&nbsp; font-size: 16px;\n}\n\n*,\n*::after,\n*::before {\n&nbsp; box-sizing: inherit;\n}\n\nbody {\n&nbsp; margin: 0;\n&nbsp; overflow-x: hidden;\n}\n\na {\n&nbsp; color: #01579b;\n&nbsp; transition: color 0.3s ease;\n}\n\na:hover {\n&nbsp; color: #00b00f;\n}\n\nh1 {\n&nbsp; text-align: center;\n}\n\nimg {\n&nbsp; max-width: 100%;\n&nbsp; height: auto;\n}\n\n.error {\n&nbsp; padding: 1rem;\n&nbsp; font-size: 150%;\n&nbsp; font-weight: bold;\n&nbsp; text-align: center;\n&nbsp; color: #fff;\n&nbsp; background-color: #dc3545;\n}\n\n.form-search {\n&nbsp; margin: auto;\n&nbsp; text-align: center;\n}\n\n.form-search input {\n&nbsp; display: block;\n&nbsp; margin: auto;\n&nbsp; padding: 0.25rem;\n&nbsp; border-radius: 0.25rem;\n&nbsp; font-size: 1rem;\n}\n\n.grid-fluid {\n&nbsp; margin: 1rem auto;\n&nbsp; max-width: 90%;\n&nbsp; display: grid;\n&nbsp; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n}\n\n.header {\n&nbsp; padding: 0.5rem;\n&nbsp; position: sticky;\n&nbsp; top: 0;\n&nbsp; text-align: center;\n&nbsp; background-color: #fff;\n}\n\n.header &gt; * {\n&nbsp; margin: 1rem auto;\n}\n\n.loader {\n&nbsp; margin: 1rem auto;\n&nbsp; display: block;\n&nbsp; width: 4rem;\n&nbsp; height: 4rem;\n}\n\n.post-card {\n&nbsp; margin: 1rem auto;\n&nbsp; padding: 1rem;\n&nbsp; width: 80%;\n&nbsp; background-color: #eceff1;\n}\n\n.post-card p {\n&nbsp; display: flex;\n&nbsp; justify-content: space-between;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En este cap\u00edtulo comenzaremos a hacer <strong>peticiones as\u00edncronas<\/strong> para ver que recogemos la informaci\u00f3n, y poder pintar cada una de las tarjetas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Archivos<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Los archivos que tenemos hasta este cap\u00edtulo son los siguientes:<\/p>\n\n\n\n<div class=\"wp-block-file alignleft\"><a id=\"wp-block-file--media-37b6ce37-e431-4a41-bb97-5ad9644f3279\" href=\"https:\/\/blog.sutilweb.eu\/wp-content\/uploads\/2024\/08\/spa-4.zip\">spa-4<\/a><a href=\"https:\/\/blog.sutilweb.eu\/wp-content\/uploads\/2024\/08\/spa-4.zip\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-37b6ce37-e431-4a41-bb97-5ad9644f3279\">Descarga<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>En el cap\u00edtulo anterior hab\u00edamos terminado de maquetar y programar la cabecera de nuestra SPA. En este cap\u00edtulo vamos a programar la&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":1646,"menu_order":6,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_uag_custom_page_level_css":"","footnotes":""},"class_list":["post-1671","page","type-page","status-publish","hentry"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"Sutil Web","author_link":"https:\/\/sutilweb.eu\/index.php\/author\/sutilweb\/"},"uagb_comment_info":0,"uagb_excerpt":"En el cap\u00edtulo anterior hab\u00edamos terminado de maquetar y programar la cabecera de nuestra SPA. En este cap\u00edtulo vamos a programar la...","_links":{"self":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/1671","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/comments?post=1671"}],"version-history":[{"count":2,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/1671\/revisions"}],"predecessor-version":[{"id":1674,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/1671\/revisions\/1674"}],"up":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/1646"}],"wp:attachment":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/media?parent=1671"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}