Files
Eric Tuvesson 53f0d6320e Initial commit
Co-Authored-By: kotte <14197736+mrtamagotchi@users.noreply.github.com>
Co-Authored-By: mikaeltellhed <2311083+mikaeltellhed@users.noreply.github.com>
Co-Authored-By: Tore Knudsen <18231882+torekndsn@users.noreply.github.com>
Co-Authored-By: Michael Cartner <32543275+michaelcartner@users.noreply.github.com>
2023-09-05 12:08:55 +02:00

493 lines
20 KiB
HTML

<!-- A step with just a popup -->
<div data-template="popup">
<video src="lesson-04_19_inspect.mp4"></video>
<h2>Data driven components</h2>
<p>Welcome back! In this fourth lesson we will learn how to use a data source to render a list of UI components. </p>
<p>In the last lesson we created a card component that we copied multiple times to create a list of cards. We will now learn how to generate the list of cards from data instead.</p>
</div>
<!-- # -->
<!-- Ask user to look at the static data -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Static data</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_04-staticarray.mp4"></video>
<h2>Static data</h2>
<p>There are many ways that we can get datasets into our project. An easy way is to use the <strong>Static Array</strong> node.</p>
<p>This node acts as a text file and supports two standard data formats: JSON and CSV. The node in this lesson comes with a small dataset following the <strong>JSON format</strong>.
<p>The dataset holds all the data for the <i>Card Item</i>s we want to render. It contains a list of titles, categories and dates for each card.</p>
</div>
</div>
<!-- # -->
<!-- Ask user to look at the static data -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Data types</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<h2>Data types</h2>
<p>Noodl is built on top of JavaScript, a language with five primary data types: <strong>number</strong>, <strong>string</strong>, <strong>boolean</strong>, <strong>array</strong> and <strong>object</strong>.</p>
<p>The editor has nodes designed to store all the different data types, but the most common way of handling data in Noodl is by using objects in arrays.</p>
<p>Let's have a closer look at this pattern.</p>
</div>
</div>
<!-- # -->
<!-- Ask user to look at the static data -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Data in Noodl</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_04-staticarray.mp4"></video>
<h2>Objects in arrays</h2>
<p>There are multiple ways of storing data in Noodl, but for our usecase the <strong>Static Array</strong> node is perfect, since it's the simplest one.</p>
<p>If you look at the structure in the Static Array node you can see that it defines an <strong>array</strong> that contains multiple <strong>objects</strong>. Each object has a set of <strong>properties</strong>.</p>
<p>In Noodl, every object automatically gets a unique id attached to it. This means that we can look up a specific object (using its id) and get its data.</b>
<p>This is one of the more tricky concepts in Noodl, but let's go forward so we can experience how it works in practice.</b>
</div>
</div>
<!-- # -->
<!-- Ask user to look at the static data -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Repeater node</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_08-repeater.mp4"></video>
<h2>Repeater node</h2>
<p>The <strong>Repeater</strong> node is used to generate visual components based on an array of objects. It takes a <strong>visual component</strong> as a template and renders it in place of the Repeater node in the Dom tree.</p>
<p>One component instance is generated and rendered for every object in the array.</p>
<p>Let's first remove the existing <i>Card Item</i> components from the DOM tree, add a Repeater node, and connect it up with our Static Array.</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. No tasks, so popup will be shown automatically -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Lesson tasks</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<image src="../01_task.png"></image>
<h2>Time to get your hands dirty!</h2>
<p>During this lesson, you will be given multiple tasks. Spot them in the lesson timeline by the <i>Task</i> label.</p>
<p>If you get stuck you can get a hint by clicking the card in the timeline.</p>
<p>Some of the nodes graphs will already be set up for you beforehand. This is to keep the lessons short so that you can focus on learning one concept at a time. If it feels like magic at times, don't worry. It's just a concept you will learn in a later lesson.</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. It has tasks, so popup will only be shown when user clicks the item -->
<div
data-conditions='[
{
"viewerpatheq":"/task-page"
}
]'
>
<div data-template="item" style="width: 280px">
<header>Task<span class="lesson-checkmark"></span></header>
<h3>Select the <strong><i>/task-page</i></strong> path in the <strong>Path Dropdown</strong></h3>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_02-selecttaskpage.mp4"></video>
<p>In this lesson you will be working on the page called <i>Task Page</i>. Navigate to it using the Path Dropdown in the Topbar.</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. It has tasks, so popup will only be shown when user clicks the item -->
<div
data-conditions='[
{
"path":"/Task Page:%Page:%Group:#Content Container:0",
"exists":false
},
{
"path":"/Task Page:%Page:%Group:#Content Container:1",
"exists":false
},
{
"path":"/Task Page:%Page:%Group:#Content Container:2",
"exists":false
}
]'
>
<div data-template="item" style="width: 280px">
<header>Task<span class="lesson-checkmark"></span></header>
<h3>In the <strong>Task Page</strong> node graph, delete the three <strong>Card Item</strong> components</h3>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_07-delete components.mp4"></video>
<p>Select the <i>Card Item</i> components and <strong>press the backspace key</strong> to delete them.</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. It has tasks, so popup will only be shown when user clicks the item -->
<div
data-conditions='[
{
"path":"/Task Page:%Page:%Group:#Content Container:%For Each",
"exists":true
}
]'
>
<div data-template="item" style="width: 280px">
<header>Task<span class="lesson-checkmark"></span></header>
<h3>Add a <strong>Repeater</strong> node as a child to the <strong>Content Container</strong> Group</h3>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_08-addrepeater.mp4"></video>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. It has tasks, so popup will only be shown when user clicks the item -->
<div
data-conditions='[
{
"path":"/Task Page:%Page:%Group:#Content Container:%For Each",
"paramseq": {
"template":"/Card Item"
}
}
]'
>
<div data-template="item" style="width: 320px">
<header>Task<span class="lesson-checkmark"></span></header>
<h3>On the <strong>Repeater</strong> node, set the <strong>template</strong> property to use the <strong><i>Card Item</i></strong></h3>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_09-cartitemtemplate.mp4"></video>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. It has tasks, so popup will only be shown when user clicks the item -->
<div
data-conditions='[
{
"from":"/Task Page:%Static Data",
"to":"/Task Page:%Page:%Group:#Content Container:%For Each",
"hasconnection":"items,items"
}
]'
>
<div data-template="item" style="width: 390px">
<header>Task<span class="lesson-checkmark"></span></header>
<h3>Connect the <strong>Static Array</strong> node to the <strong>Repeater</strong> node and send the <strong><i>items</i></strong> output to the <strong><i>items</i></strong> input</h3>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_09-connectarray.mp4"></video>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. No tasks, so popup will be shown automatically -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Mapping data</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_10_mappingdata.mp4"></video>
<h2>Mapping data</h2>
<p>You now have 4 cards in your UI, each with unique data. Let's walk through what happened here.</p>
<p>You already created the <i>Card Item</i> component in the last lesson. There you also created ports on the <i>Card Item</i> using a <strong>Component Inputs</strong> node. Those ports where hooked up to the properties we wanted to overwrite.</p>
<p>If the port names on the Component Inputs node matches the object keys in the Repeaters array, that data will automatically be passed to the rendered component.</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. No tasks, so popup will be shown automatically -->
<div>
<div data-template="item" style="width: 260px">
<header>&nbsp;</header>
<h2>Making clickable cards</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_13_connectclicked.mp4"></video>
<h2>Making clickable cards</h2>
<p>You have now built the basic system for showing cards (or any other type of list) from data. But to take this a step further you can also implement a way to make each card clickable and get its associated object so we can use that data somewhere else.</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. No tasks, so popup will be shown automatically -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Component Outputs node</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_12_componentoutput.mp4"></video>
<h2>Component Outputs node</h2>
<p>Just as the Component Inputs node can be used to get data and signals into a component, you can use a <strong>Component Outputs</strong> node to send data and signals out from a component.</p>
<p>In this case we want to make the <i>Card Item</i> clickable, so that we can receive a signal from the card when it's clicked.</p>
<p>Let's start by creating a <strong>Component Outputs</strong> node in our <i>Card Item</i> component</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. It has tasks, so popup will only be shown when user clicks the item -->
<div
data-conditions='[
{
"path":"/Card Item:%Component Outputs",
"exists":true
}
]'
>
<div data-template="item" style="width: 340px">
<header>Task<span class="lesson-checkmark"></span></header>
<h3>In the <strong>Card Item</strong> node graph, create a <strong>Component Outputs</strong> node</h3>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_12_componentoutput.mp4"></video>
<p>Open the <i>Card Item</i>component, open the Node Picker and place a Component Outputs node anywhere in the node graph.</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. It has tasks, so popup will only be shown when user clicks the item -->
<div
data-conditions='[
{
"path":"/Card Item:%Component Outputs",
"hasport": "Clicked"
}
]'
>
<div data-template="item" style="width: 270px">
<header>Task<span class="lesson-checkmark"></span></header>
<h3>Create a port called <strong><i>Clicked</i></strong></h3>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_13_clicked.mp4"></video>
<p>Remember that the port names are case sensitive</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. It has tasks, so popup will only be shown when user clicks the item -->
<div
data-conditions='[
{
"from": "/Card Item:%Group",
"to": "/Card Item:%Component Outputs",
"hasconnection": "onClick, Clicked"
}
]'
>
<div data-template="item" style="width: 450px">
<header>Task<span class="lesson-checkmark"></span></header>
<h3>Connect the <strong>Card</strong> Group node to the <strong>Component Outputs</strong> node and send the <strong><i>click</i></strong> output to the <strong><i>clicked</i></strong> input</h3>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_13_connectclicked.mp4"></video>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. No tasks, so popup will be shown automatically -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Repeaters and Component Outputs</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_14_outputs.mp4"></video>
<h2>Repeaters and Component Outputs</h2>
<p>If you just had a single Card component you would now be able to get the click event in the node graph where the <i>Card Item</i> component is placed.</p>
<p>Since the <i>Card Item</i>s are generated by the Repeater node, we can't access that port directly, so you need a way to know which of the four cards you click.</p>
<p>Earlier in this lesson we talked about how each object in the array has a unique id. This is really handy, as you can make the Repeater node give us the object id of the card instance we click.</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. No tasks, so popup will be shown automatically -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Object node</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_15_objects.mp4"></video>
<h2>Object node</h2>
<p>The <strong>Object</strong> node gives you a way to access an object and its data anywhere in a project. You only need to provide it with an object id.</p>
<p>Objects are generally a good way to share data between different node graphs.</p>
<p>Let's look at how the Object and Repeater nodes can be used together to get the object data from a clicked <i>Card Item</i>.</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. It has tasks, so popup will only be shown when user clicks the item -->
<div
data-conditions='[
{
"path":"/Task Page:%Model2",
"exists":true
}
]'
>
<div data-template="item" style="width: 350px">
<header>Task<span class="lesson-checkmark"></span></header>
<h3>In the <strong>Task Page</strong> node graph, place an <strong>Object</strong> node adjacent to the <strong>Repeater</strong> node</h3>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_15_objects.mp4"></video>
<p>Navigate to the <i>Task Page</i> component using the Component Panel in the Sidebar. Then open the Node Picker and create a new Object node.</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. It has tasks, so popup will only be shown when user clicks the item -->
<div
data-conditions='[
{
"from": "/Task Page:%Page:%Group:#Content Container:%For Each",
"to": "/Task Page:%Model2",
"hasconnection": "itemActionItemId, modelId"
}
]'
>
<div data-template="item" style="width: 400px">
<header>Task<span class="lesson-checkmark"></span></header>
<h3>Connect the <strong>Repeater</strong> node to the <strong>Object</strong> node and send the <strong><i>item id</i></strong> output to the <strong><i>id</i></strong> input</h3>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_17_connectid.mp4"></video>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. It has tasks, so popup will only be shown when user clicks the item -->
<div
data-conditions='[
{
"from": "/Task Page:%Page:%Group:#Content Container:%For Each",
"to": "/Task Page:%Model2",
"hasconnection": "itemOutputSignal-Clicked, fetch"
}
]'
>
<div data-template="item" style="width: 400px">
<header>Task<span class="lesson-checkmark"></span></header>
<h3>Connect the <strong>Repeater</strong> node to the <strong>Object</strong> node and send the <strong><i>clicked</i></strong> output to the <strong><i>fetch</i></strong> input</h3>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_18_clickfetch.mp4"></video>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. No tasks, so popup will be shown automatically -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Click the cards</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<video src="lesson-04_19_inspect.mp4"></video>
<h2>Click the cards</h2>
<p>Try <strong>hovering</strong> over the Object and pin the Data Popup so you can inspect the change when the <i>Card Item</i>.</p>
<p>As you can see you now get the object id, and all the associated data from the specific card that is clicked. This is a very powerful pattern that is used in almost every app.</p>
</div>
</div>
<!-- # -->
<!-- A step with an item in the bottom bar. No tasks, so popup will be shown automatically -->
<div>
<div data-template="item">
<header>Outro</header>
<h2>Congratulations!</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<!--<img src="tutorial_card.png" style="cursor: pointer;" onclick="window.open('https://www.youtube.com/watch?v=TNnn0Gzj-H4&list=PL2eC2vS4uVoMbujQ5CiNtNuP7s7-UwNn-')"> -->
<h2>Congratulations!</h2>
<p>You've completed the fourth tutorial! Great job!</p>
<p>If you are new to programming, you might be interested in reading a little more about the different data types in JavaScript.</p>
<p>In the next tutorial we will learn how to use the click event on our cards to navigate to a detailed page with dynamic data from each card.</p>
<p>Happy Noodling!</p>
<!--<button style="width: 150px" onclick="window.open('https://www.youtube.com/watch?v=TNnn0Gzj-H4&list=PL2eC2vS4uVoMbujQ5CiNtNuP7s7-UwNn-')">WATCH TUTORIAL</button>-->
<button style="width: 150px" data-click="exitEditor">EXIT LESSON</button>
</div>
</div>
<!-- # -->