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>
This commit is contained in:
Eric Tuvesson
2023-09-05 12:08:55 +02:00
commit 53f0d6320e
2704 changed files with 76354 additions and 0 deletions

View File

@@ -0,0 +1,492 @@
<!-- 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>
<!-- # -->

View File

@@ -0,0 +1,70 @@
<!-- Ask user to look at the static data -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Numbers</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<h2>Numbers</h2>
<p>A number is (unsurprisingly) a number. It can only contain numbers, and is used anytime you want to store values that can be increased/decreased or be used in a calculation.</p>
</div>
</div>
<!-- # -->
<!-- Ask user to look at the static data -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Strings</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<h2>Strings</h2>
<p>A string is a piece of text. It starts and ends with a single <strong><i>"</i></strong>. Anything in between will be treated as written text, so it can not be used for calculations (even if it contains numbers).</p>
<p>In fact, adding one string to another just results in one longer string. Examples include <strong>"Hello" + "world" = "Helloworld"</strong> or (the slightly dumber) <stong>"13" + "37" = "1337"</stong>.</p>
</div>
</div>
<!-- # -->
<!-- Ask user to look at the static data -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Booleans</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<h2>Booleans</h2>
<p>A boolean is simply a value that is either <strong><i>true</i></strong> or <strong><i>false</i></strong>. It is very useful when building logic.</p>
</div>
</div>
<!-- # -->
<!-- Ask user to look at the static data -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Arrays</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<h2>Arrays</h2>
<p>An array is a list of <strong>items</strong> (that can be of any data type, even another array). It starts with a <strong><i>[</i></strong> and ends with a <strong><i>]</i></strong>. The array can be of any length, an the items are separated with a <strong><i>,</i></strong> between them.</p>
</div>
</div>
<!-- # -->
<!-- Ask user to look at the static data -->
<div>
<div data-template="item">
<header>&nbsp;</header>
<h2>Objects</h2>
</div>
<div data-template="popup">
<style>.lesson-item-popup {width: 600px !important;}</style>
<h2>Objects</h2>
<p>An object is a list of <strong>properties</strong>. It starts with a <strong><i>{</i></strong> and ends with a <strong><i>}</i></strong>. Every property has a <strong>key</strong> and a <strong>value</strong>, with a <strong><i>:</i></strong> between them. The key is the "name" of the property and the value is the data that the property holds. We use the keys to be able to get specific data from the object. The value can be of any type (even another object).</p>
</div>
</div>
<!-- # -->

Binary file not shown.