I am new to Fable. I need to convert this html code (this is just a simplified sample, and btw not mine) into the Fable.React syntax.
<div id="templatemo_header">
<div id="site_title">
<h1>
<img src="/Content/images/templatemo_logo.png" />
</h1>
</div>
</div> <!-- end of header -->
<div>
<div id="templatemo_menu">
<ul>
<li><a class="current" href="/">Some text</a></li>
</ul>
</div> <!-- end of templatemo_menu -->
<div id="templatemo_main">
<div id="templatemo_content">
<p id="3">
Some text......
</p>
</div> <!-- end of content -->
</div> <!-- end of main-->
</div>
I can convert the html code into the Elmish code with the help of this converter, but how to adapt the resulting code into Fable.React? Do you know of any example I could study? So far I have not been able to find any. Probably id should be Props.Id, class should be Props.Class, etc. Where to find the appropriate syntax and indentation?
open Fable.React
let view (model: Model) (dispatch: Msg -> unit) =
div [ Props.Id "templatemo_header" ]
[ div [ Props.Id "site_title" ]
[ h1 []
[ a [ Props.Href "/" ]
[ img [ Props.Src "/Content/images/templatemo_logo.png" ]
[]
]
]
]
]
, div [] //the comma here looks like a problem
[ div [ Props.Id "templatemo_menu" ]
[ ul []
[ li []
//The comma in the <a> tag looks like a problem
//Or maybe having more than one attribute is a problem
[ a [ Props.Class "current", Props.Href "/" ]
[ text "Some text" ] //text seems to be a problem
]
]
]
, div [ Props.Id "templatemo_main" ]
[ div [ Props.Id "templatemo_content" ]
[ p [ Props.Id "3" ]
[ text "Some text......" ]
]
]
]
The converted code does not work (as I have expected). I get error messages such as "Error FS0003 This value is not a function and cannot be applied".
Btw, I did find examples of how to convert html code into Feliz manually (fewer lists - the code then looks better), but manually re-writing the entire third-party html code that I received is out of option for me.
I think you're look for Feliz syntax, which is documented well in The Elmish Book. A quick translation of your first div would look something like this:
open Feliz
Html.div [
prop.id "templatemo_header"
prop.children [
Html.h1 [
Html.a [
prop.href "/"
prop.children [
Html.img [
prop.src "/Content/images/templatemo_logo.png"
]
]
]
]
]
]
Related
I have a page where a user gets to decide between different products, here is the list in my View page:
items: [
{
id: 1,
name: "Product_1",
children: [
{ name: "Order", id: "62c40e2faba699b309005102", popup: "order" },
{ name: "Feedback", id: "62c40e26aba699b309005100", popup: "feedback" },
],
},
{
id: 2,
name: "Product_2",
children: [
{ name: "Pre-Order", id: "62c404228ce80aac470a1339", popup: "preOrder"},
],
},
When they do, different form block components should appear in a popup, here is the list of the different combinations in a different file:
computed: {
order(){
return [
{name : "personal info" , component:"PersonalInfo"},
{name : "credit card" , component:"CreditCard"},
]
feedback(){
return [
{name : "personal info" , component:"PersonalInfo"},
{name : "feedback text" , component:"FeedbackText"},
]
preOrder(){
return [
{name : "email" , component:"Email"},
{name : "order details" , component:"OrderDetails"},
]
},
So if they want to order product one: they should see the form popups asking them to enter personal info and credit card info,
if they want to give feedback to product 1: they should see the form popups asking them to enter personal info and feedback input text,
if they want to order product 2, they can only preorder it yet so they should enter their email info and give details about the preorder.
When I hard code one of the keys like this, it works, and I have the 2 components called by feedback() that render.
<li v-for="item in feedback" v-bind:key="item.name">
<span class="item-title">{{item.name}}</span>
<component :is="item.component" />
</li>
However, when I try to change the v-for for a dynamic value that changes based on which product the user clicks on, I get an error (says popup is not defined). :
<li v-for="item in items.children.popup" v-bind:key="item.name">
<span class="item-title">{{item.name}}</span>
<component :is="item.component" />
</li>
The items are passed as a prop from the parent page to the child component like this:
in parent:
<popUps
v-if="show"
:show="show"
:items="items"
#close="show = false"
></popUps>
in child:
props: ["show", "items"],
So I'm not sure how to write the v-for part to access the functions order(), feedback() or preorder() and then render the component accordingly.
The mistake is made when you've tried to loop on 'item.children.popup', which is undefined (item.children is an array and not an object).
You should update your code like that :
1 - Put your computed variables in one computed variable called componentsDeclaration :
computed: {
componentsDeclaration(){
return {
order : [
{name : "personal info" , component:"PersonalInfo"},
{name : "credit card" , component:"CreditCard"},
],
feedback : [
{name : "personal info" , component:"PersonalInfo"},
{name : "feedback text" , component:"FeedbackText"},
],
preOrder : [
{name : "email" , component:"Email"},
{name : "order details" , component:"OrderDetails"},
]
}
}
},
2 - Access to the popup content by using 'componentsDeclaration' :
<li v-for="item in items.children" v-bind:key="item.name">
<div v-for="subItem in componentsDeclaration[item.popup] v-bind:key="subItem.name">
<span class="item-title">{{subItem.name}}</span>
<component :is="subItem.component" />
</div>
</li>
Hello i wan't to loop two differents arrays inside one component like this
operationMep= [
{
"id": 15525205,
"type": "mise_en_prep",
"orderOperationSkus": [
{
"id": 24339529,
"orderSku": {
"id": 11747818,
"referenceMep": "MB0153",
"tax": 20,
"size": "M"
}
}
}
]
operationInvoice= [
{
"id": 16525205,
"type": "invoice",
"orderOperationSkus": [
{
"id": 24339529,
"orderSku": {
"id": 11747818,
"referenceInvoice": "MB0153"
}
}
}
]
<div v-for="itemMep in operationMep">
<my-template
v-for="itemVoice in operationInvoice"
:size="itemMep.size"
:invoice="itemVoice.referenceInvoice">
</my-template>
</div>
it's possible to do that because i have 2 loop inside this component and i want to add a condition if operation invoice is null just loop operationMep. thank you
If I understand correctly, you want to avoid rendering the nested <my-template> if operationInvoice is null.
You could wrap the nested v-for loop with v-if="operationInvoice":
<div v-for="itemMep in operationMep">
<template v-if="operationInvoice">
<my-template
v-for="itemVoice in operationInvoice"
:size="itemMep.size"
:invoice="itemVoice.referenceInvoice">
</my-template>
</template>
<!-- other markup here -->
</div>
I have to iterate some articles which contain images inside. The thing is that it doesn't work what I'm doing.
I have tried an v-for inside the article ad then, binding the src like this:
<section class="articulos b-flex b-flex-wrap b-flex-center b-flex-center-horizontal">
<article v-for="imagen in imagenes">
<figure class="contenedor-articulo">
<img v-bind:src="'../assets/img/' + imagen.url" />
<figcaption>
<h3>Ensaladilla Rusa</h3>
<p>+ 0,50 €</p>
<i class="fas fa-plus-circle"></i>
</figcaption>
</figure>
</article>
</section>
the script of the component is like this:
<script>
export default {
name: 'Articulos',
data() {
return {
imagenes: [
{url:"apeteat_2019_ensaladaquinoachicken.jpg"},
{url:"apeteat_2017__ensaladilla_rusa.jpg"},
{url:"apeteat_2018_nigirimix.jpg"},
{url:"apeteat_2019_wrapcesar.jpg"},
{url:"apeteat_2019_ensaladaquinoachicken.jpg"},
{url:"apeteat_2018_nigirimix.jpg"}
]
}
}
}
</script>
I have this error message:
message: error: Elements in iteration expect to have 'v-bind:key' directives (vue/require-v-for-key) at src/components/Articulos.vue:4:9:
2 |
3 | <section class="articulos b-flex b-flex-wrap b-flex-center b-flex-center-horizontal">
> 4 | <article v-for="imagen in imagenes">
| ^
5 |
6 | <figure class="contenedor-articulo">
the image is not displaying. Tha image url is so:
src="../assets/img/apeteat_2019_ensaladaquinoachicken.jpg", before iterating thwy were displaying perfectly.
Add unique key when use v-for.
<article
v-for="(imagen, index) in imagenes"
:key="index"
>
Using index as key is not recommended. Please add unique key or id in each image object like below.
[
{
id: 1,
url:"2019_ensaladaquinoachicken.jpg"
},
...
]
...
<article
v-for="imagen in imagenes"
:key="imagen.id"
>
I guess the problem with your imagenes array.
Instead of this (array with one object with duplicated keys):
imagenes: [{
url:"2019_ensaladaquinoachicken.jpg",
url:"2017__ensaladilla_rusa.jpg",
url:"2018_nigirimix.jpg",
url:"2019_wrapcesar.jpg",
url:"2019_ensaladaquinoachicken.jpg",
url:"2018_nigirimix.jpg"
}]
It most likely should be this (array of objects):
imagenes: [
{ url:"2019_ensaladaquinoachicken.jpg" },
{ url:"2017__ensaladilla_rusa.jpg" },
{ url:"2018_nigirimix.jpg" },
{ url:"2019_wrapcesar.jpg" },
{ url:"2019_ensaladaquinoachicken.jpg" },
{ url:"2018_nigirimix.jpg" }
]
You need to add a '/' in your path binding like this : v-bind:src="'../assets/img/apeteat_/' + imagen.url"
Also, rewrite your imagenes array to be like this (they key 'url' is duplicated):
imagenes: [
{url: //img name },
{url: //img name }
//etc
]
In HTML
<article v-for="imagen in imagenes" :key="imagen.id">
<img :src="require(`#/assets/${imagen.imagenes}`)" />
...
</article>
In JS
imagenes: [
{id:1, url:"apeteat_2019_ensaladaquinoachicken.jpg"},
{id:2, url:"apeteat_2017__ensaladilla_rusa.jpg"},
{id:3, url:"apeteat_2018_nigirimix.jpg"},
{id:4, url:"apeteat_2019_wrapcesar.jpg"},
{id:5, url:"apeteat_2019_ensaladaquinoachicken.jpg"},
{id:6, url:"apeteat_2018_nigirimix.jpg"}
]
I connected to a URL using Axios using this:
getUsers: function() {
axios.get(urlUsers).then(response => {
this.lists = response.data
});
and get this data:
"lists": [
{
"name": "Destacados",
"tags": [
"Aguila"
],
"isRoot": true,
"products": [
{
"name": "Coors",
"code": "139017",
And tryng to list products.
How?
You can use v-for to render lists. In your case you have a nested array so you would need to do it twice. However I think you should change your data element 'lists' and remove all the excess quotes ("") so it looks like this:
lists: [
{
name: "Destacados",
tags: [
"Aguila",
],
isRoot: true,
products: [
{
name: "Coors",
code: 139017,
},
{
name: "Bud",
code: 139019,
}
],
}
]
and then run your v-for loops:
<template>
<div v-for="list in lists" :key="list.name">
<ul v-for="product in list.products :key="product.name">
<li>{{product.name}}</li>
<li>{{product.code}}</li>
</ul>
</div>
</template>
Well, this problem has me stumped... Having a bit of trouble getting nested for-loop data to show up:
<div v-if = "private.folders!=null" v-for="folder in private.folders">
{{folder.name}}
<div v-for="check in folder.checks">
{{check.name}}
</div>
</div>
And then the data that I'm trying to use looks like this:
folders [Array]
-object [this is a single 'folder']
--name
--checks [array] [each folder has this array]
---[object] [the actual 'check' object]
----[name]
The outer loop works just fine, and returns the data I expect. However, check.name doesn't return anything, and there are no errors in the console. Is it possible to do nested for-loops like this?
I tested you template, it's works.
new Vue({
el: '#sample',
data: {
private: {
folders : [{
name : 'folder1',
checks : [
{ name : 'check1.1' },
{ name : 'check1.2' }
]
},
{
name : 'folder2',
checks : [
{ name : 'check2.1' },
{ name : 'check2.2' }
]
}
]
}
}
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
<div id="sample">
<div v-if = "private.folders!=null" v-for="folder in private.folders">
{{folder.name}}
<div v-for="check in folder.checks">
{{check.name}}
</div>
</div>
</div>
This is how you might set it up with HTML table:
new Vue({
el: '#sample',
data: {
private: {
folders : [{
name : 'folder1',
checks : [
{ name : 'check1.1' },
{ name : 'check1.2' }
]
},
{
name : 'folder2',
checks : [
{ name : 'check2.1' },
{ name : 'check2.2' }
]
}
]
}
}
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
<div id="sample">
<table>
<tr>
<th>Folder</th>
<th>Checks</th>
<th>Checks</th>
</tr>
<tr v-if = "private.folders!=null" v-for="folder in private.folders">
<td><b>{{folder.name}}</b></td>
<td v-for="check in folder.checks">
{{check.name}}
</td>
</tr>
</table>
</div>