Skip to main content
Version: Next

Composition and Components

Introduction

Welcome back Olympian ☀️

In the last chapter we created our first UI application and added a bit of Logic in it.

In this chapter we will see how to solve a very common problematic in UI development. Along this we will discover the Image component, create a new app with composition and speak about scopes and other things 😃

A New App: Slide Show

Did you one day dream of sharing your pictures with your family and friends, on an online website?

If yes, that's great! As we will create a Slide Show application during this chapter.
If not, well we will do it anyway, this small project is for learning new concepts in the end 😉

So first let's setup a new UI App called Slide Show (where you want, I use my My Exercises folder personnally). In it you can create 3 screens (Owl Screen, Kingfisher Screen and Parrot Screen) and connect them like this:

Let's enter the Owl Screen: now how to show an image or a picture in DRAW?
You can try to find it in the Marketplace 😉

You may have guessed it but yes, DRAW provide a Visual Component to do just that: the Image component!

But to show a picture we need one. Here you can just copy this link (it is an owl picture):
https://cdn.pixabay.com/photo/2012/06/19/10/32/owl-50267_960_720.jpg

With this link copied, we can create our first even Image in DRAW:

Easy right 😉

You can play around with the other properties, but the default values are usually fine.
Still you may wonder why there is an Image property and an Image URL one. That's because we have two way of using pictures in DRAW:

  1. With Image URL, this is when the picture is hosted on another server and you can show it with an URL.
  2. With Image, this is when the picture is stored in DRAW directly! To achieve that you can check the Media Library brick in the Marketplace when you are in the Project Editor 😉

For our Slide Show app the Image URL property will be enough.
I already searched for some birds 🐦 pictures online, you can save those URLs:

Until now there is still no sight of any problem. Bear with me, we are almost there!

The Problem: Time is Limited

For our Slide Show the Image alone is not enough, we need a Button to switch from one screen to the next one. And for good measure we can also add a Label as a title for each picture.

Okay so let's continue with the Owl Screen, we already did:

  1. Add the Image component from the Marketplace
  2. Eventually renamed it in the Layers panel.
  3. Set its Image URL property.

Now what is left to do:

  1. Position and size the Image nicely, so 4 properties: X, Y, Width, Height
  2. Add the Label and set its properties: Text, Text Variant, Text Color, Horizontal Align, X, Y, Width, Height
  3. Add the Button and set its properties: Text, Variant, End Icon, X, Y, Width, Height

That was some steps, but with a bit of practice it's actually not that long.
Cool so let's continue with the Kingfisher Screen now, we do:

  1. Add the Image 😃 and set its properties: Image URL, X, Y, Width, Height
  2. Add the Label 😓 and set its properties: Text, Text Variant, Text Color, ...
  3. Add the Button 😴 and ...

See where I am going with this?

We are doing the exact same steps over and over again!

And this is problematic in many ways:

  1. It takes a lot of time, we all now that time is precious, and we only did it for 3 pictures!
  2. It is not fun, and developing should be fun and not bothersome.
  3. It is not maintainable. Imagine after doing 7 screens that you want to change the Label color? You will need to do it manually 7 times!
  4. Developers are by essence lazy, they take time to create application to gain time later on 😃

Hopefully for us, this is a very common issue in all programming languages and there are multiple solutions to it.
DRAW is not different and we will see how to handle that 💪

The Solution: Composition

So how can we solve this issue?

As for all problem, let's start by assessing what we have (or may have):

We have 3 screens, and each of them contains exactly the same components: a Label, an Image and a Button.

Would it not be nice to regroup those 3 components? And use only 1 component in the screens?

I cannot create any suspense here 😆
Yes! This is the solution and it is called Composition.

We will create a brand new Visual Component that contains our 3 components, and then the screens will directly use this new Visual Component that we created 😉

  • We will significantly reduce the number of steps required.
  • Also if we want to change the title color for example, only 1 step is required.

What is this word Composition exactly? Let me try to explain it:

See how the Visual Component contains 3 components? Another phrasing would be: the Visual Component is composed of 3 components 😉 In this same logic, our screens are each composed of 1 component: our brand new Visual Component. Another example: our UI App is composed of one Screenflow, which itself is composed of 3 screens!

For a more advanced explanation, check the Wikipedia page: https://en.wikipedia.org/wiki/Object_composition

tip

Fun fact: another ancient name of DRAW was the Composer.

Okay enough talking, let's see how to do that with Olympe!

Our First Visual Component

Until now we only used Visual Component that already existed: Label, Button, TextField and Image.

Those components are common to most application, that's why there are provided by default. But as you can imagine now, we can also create our own Visual Component that do what we want it to do.

Check this gif and create your first Visual Component, call it Slide Show Image:

Enter it and here we are, the Visual Component Editor!
It looks a lot like the Screen Editor isn't it? Yes it does, we will speak a little bit more about that later in this chapter. For now all you need to remember: both editors work exactly the same! So everything we learnt in the last chapter is true here 😉

That also means that it has a Spec&Doc Tab to edit the properties, events and documentation.
Go in it and create those properties and events, we will need them:

Now go ahead and add the components, follow this gif for guidance:

Cool! Let's set the position and size now. Instead of setting them with constant numbers as we did before. Let's use the special functions provided. Check this gif to understand what to do, you can also play with it:

That's nice isn't it 😉

Those special functions are quite explicite in what they do, but I felt like a little explanation would still be useful:

  1. Notice the little button right to Display. This is the Wireframe view, basically it shows the borders of each components. This can be very useful when placing them or also when you have an invisible component.
  2. The X property that you already know, I use here the Center special function which centers the component horizontally.
    • (I have the Label selected)
  3. The Y property that you also already know, I use here the Top special function which put the component at the top vertically. I could use the constant value zero in this case, the result would be the same.
  4. The Width property with the special function Percentage. A value of 90 means that the component will be 90% of the Slide Show Image width. If the Slide Show Image is 100px wide, then the value is 90px. If it is 200px wide, then the value is 180px. And so on.
  5. Same as for Width but for the Height this time, 10%.

Let's Bind with the Prop Picker

We have our components in place, but how can we show a different title and image in each screen? For that we will make some properties dynamic by adding logic to them. And their values will be configured in the screens directly.

How can we do that? With the Prop Picker! And by doing what is called: Binding

Binding is about linking the value of a property of a component, to another property of another component:

  • We want to bind the Text property of the Title Label to be the value of the property image title of our component Slide Show Image (remember: we already created it).
  • We want to bind the Image URL property of the Image to be the value of the property image url of our component Slide Show Image.
  • We want to bind the On Click event of the Next Button to dispatch the on next clicked event of our component Slide Show Image.

So let's do just that, in this gif we bind the Image and the Button:

Go ahead and try to do it for the Label too before checking the gif:

After binding the label, you will not see it anymore! That's normal, the image title being empty, the Text property is then also emtpy. To solve that an easy way is to use a default value for the property image title. The gif shows how to do just that 😉

To do all those bindings we used the Prop Picker, let's have one more look at it:

  1. The Prop Picker is about accessing a property or an event on a specific component. What you can access is the parent (in our case the Slide Show Image) and the children (the 3 components), this is what we call a scope and I will speak about it in a short time.
  2. The properties are listed here, with the name and the type between parenthesis.
  3. You can filter the properties by typing the part of the name here, like the search bar in the Marketplace.
  4. After selecting the property, you have the choice for three actions:
    • Get Value will create the brick Get UI Property, it is for getting the value of the property.
    • Set Value will create the brick Set UI Property, it is for setting the value of the property.
    • Feed Value will create the brick Feed UI Property, it is for _setting the value of the property continuously. This is a very specific one and we don't need to understand it for now.

It works almost the same for events, only the actions changes: dispatch and listen.

  • We already used the brick Dispatch Event (created with Dispatch button), it triggers an event. It is for starting the event: like hey! this happened or hey! do this.
  • Listening to an event is the exact contrary, it is was to do after the event was triggered. When we add logic on the On Click event of the Button, that's exactly what we do.

Okay our Slide Show Image component is now ready for usage in our screens 🎉

But before that I want to talk a bit about scopes.

A Little Peak onto Scopes

The concept of scopes is a little bit more advanced, but hopefully at the end you can grasp at least something from it. Especially understanding a bit more why bindings are important and also what are the purpose of it. It should also make the purpose of the Prop Picker more obvious.

Let's start with a first schema:

Here we are representing the scope of the Screenflow. The yellow arrows shows who can bind with who, let's get into some therminology here:

  • The Screenflow is the parent, and it can interacts with its children.
  • Each screen is a child, and they can interacts with the parent and their siblings (the other children).

However the parent cannot interacts with its grand-children (what is inside the screens).
Also a child cannot interact with the children of a sibling (also what is inside).

Let's do the same schema but for the Slide Show Image component we created:

See how similar it is? The therminology is exactly the same, as for who can interact (bind) with who 😉

The bindings we did in the last chapter are here:

  • We could only use the Prop Picker on those 4 components (1 parent and 3 children).
  • The Text property of the Title Label is bound with the image title property of its parent.

And this is exactly what a scope is. It is who (or what) a specific component can bind with 😉

Let's continue the exercise a bit further with the scope of a single screen, Owl Screen:

We did not do it yet, but the screen will be composed of a Slide Show Image component.

And this is where we will configure the component differently in each screen! The Owl Screen does not have access to its grand-children to change the Title Label directly, but it can set the image title of the Slide Show Image, and this value will then propagate down.

To go a little deeper let's combine all the schemas together:

Here I changed the arrows colors to really show who can interact with who 😉

In this schema we can see some kind of frontiers:

  • Between the blue arrows that are inside the Slide Show Image and the red arrows that are outside.
  • Between the red arrows that are inside the Owl Screen and the yellow arrows that are outside.

Let's zoom in at one of those frontier to see what live there:

Properties and Events! This is what make the bridge from the inside to the outside, and vice-versa 😃
And we can see the actions that the Prop Picker allows us to do with them!

From an inside point of view:

  • We can get the value of a property that was set from the outside.
  • We can set the value of a property that the outside can then get.
  • We can dispatch an event, and the outside can listen to it.
  • We can listen to an event, the outside can also dispatch it for the inside to know.

From an outside point of view it is the same, but in reverse.

And that wraps up this section about scopes. Do not worry if it is not all clear yet.
In the end it is just a story of who can speak with who, and how properties and events are the messagers 😉

Pictures Slideshow

We are almost done with our little Slide Show app, let's put the Slide Show Image to work!

First the Owl Screen, the component we created can now be found in the Marketplace directly 😉

Here is a gif of the process:

It is the same for the Kingfisher Screen, try it by yourself! Here the gif for reference:

And last but not least, the Parrot Screen:

Do you feel how fast it was to setup those 3 screens?
Indeed we took some time to create the Slide Show Image component, but after that the screens are a breeze.

And that is the power of composition 💪

Before we can test our application, we need to setup the transitions in the Screenflow. In the previous chapter we create a new event on the screen, then dispatched it in the button On Click. This is very common to do and also quite cumbersome. Luckily the Screenflow Editor has our back and there is a quicker way to do it.

Check this out:

And same for the two remaining transitions:

Yay 🎉 Go ahead and test the app!

The Title Color is Bad

Remember what we talked about: how composition would help us change the title color in only one step?

You can try to do it 😉 Here is the gif that demonstrate just that:

tip

By double-clicking on the Slide Show Image in the Owl Screen, it directly jumps inside the component editor 😉

Screen vs Visual Component

We noticed that the Screen Editor looks and works the same as the Visual Component Editor. So why do we need both? And what are the differences between them? I promised you to speak about that, so here we are.

The short answer is that both editors are exactly the same because a Screen is a Visual Component. And there is actually no Screen Editor, we use the Visual Component Editor in both cases.

The contrary however is not true: not all Visual Component are Screens.

We need Screen for one reason: to use it in the Screenflow 😉
But other than that, a Screen is exactly like the Slide Show Image or a Label. However it can not be used in a place other than the Screenflow.

Here is a little table to resume it:

ScreenVisual Component
Is a Visual Component?YesYes
Has properties?YesYes
Has events?YesYes
Can be used in Visual Component?NoYes
Can be used in Screen?NoYes
Can be used in Screenflow?YesNo

Conclusion

That's it for this chapter, congrats!

With the last chapter and this one about UI and Composition, you can already do some quite fancy applications 😉
This may sound overwhelming but trust me, at this point you probably just miss practice 💪

Of course there are still some important concepts to learn before being an Olympe god!
In the next chapter we will go back into the Logic world, and speak about interactions with Action.

Project Practice

It's project time! 🎉

Without further do, let's put into practice what we learnt in this chapter.

Go to your Guess the Number project and create a new folder called UI, in it you can create a new Visual Component called Content Component.

This is the component you need to create:

Try to reproduce as much a possible by yourself, below are all the properties and values I used.
There are some special things we didn't use yet:

  1. Content Component:
    • In the 3rd tab: Allow Content Overflow should be set to True
    • Add property description of type Text, default value is "_description_"
    • Add property action of type String, default value is "<action>"
    • Add event on action clicked
  2. BG Rectangle of type Rectangle:
    • X, Y, Width and Height: Center, Middle, 100%, 100%
    • Color (in the 3rd tab): #FFFFFF (white)
    • Border Radius: 12
    • CSS Property: "box-shadow: 6;"
  3. Title Label of type Label:
    • Text: "**Guess the Number!**"
    • Text Variant: Heading 2
    • With Format: True (activated / enabled)
      • Read the Label documentation to understand what is happening with this property 😉
    • Text Color: #06A898 (green, choose what you like)
    • Horizontal Align: Center
    • X, Y, Width and Height: Center, 37, 90%, 72
  4. Description Label of type Label:
    • Text: bind it with description
    • With Format: True
    • Text Color: same as the Title Label
    • Horizontal Align: Center
    • X, Y, Width and Height: Center, 140, 90%, 200
  5. Action Button of type Button:
    • Text: bind it with action
    • MUI sx [json]: "{"fontSize":"32px"}"
    • Y, Width and Height: 370, 210, 70
    • X: bind a dynamic value
      • The formula is: X = (Description Label).X + (Description Label).Width - (Action Button).Width
      • (Description Label).X means the property X of the component Description Label
      • Hint: This is the perfect time to use the Prop Picker more extensively (3 times!)
      • Hint: You will need the brick Plus and the brick Minus
    • Color (in the 3rd tab): same as the Title Label
    • On Click: dispatch the event on action clicked

Add the Component in Screens

Now let's add it in the four screens, do that and set the X, Y, Width and Height as follow: Center, 50, 650, 470

Now the action property:

Home ScreenPlay ScreenWin Screen_Loose Screen
action"Play!""Guess""New Game""Try Again"

In the on action clicked event you can just dispatch the event of your choice to go to the next screen.
We will add what is missing in the next chapter 😉

To finish this practice, let do the description property.

Description: Home Screen

In the Home Screen the value is:

The objective of this game is to guess the _Mystery Number_! 
- The number is between 1 and 100 (inclusive)
- You have max 10 attempts to guess it

Click on the **Play!** button to start:

Yes it is a multiline string. We can do that because we chose Text instead of String for the description type. Notice also the markdown usage, read the Label documentation if you don't know what I'm talking about.

Description: Play Screen

Now in the Play Screen we will use a dynamic value:

The first input value is this one:

Enter a number between 1 and 100 and click the **Guess** button.

You have **$1** attempts left.

**$2**

The Format String brick is a bit like the Concat brick, but much more powerful to use.
Check out its documentation!

Let's stay in the Play Screen, we need another component for the player to enter its guess:

  • Guess TF of type TextField:
    • Type: Number, Color: Success, Auto Focus: True
    • X, Y, Width and Height: Center, 420, 125, 70

Description: Win Screen

Now in the Win Screen we will also use a dynamic value:

The first input value is this one:

**Congrats!** You guessed right!

The Mystery Number was **$1**.
You took **$2** attempts to find it!

Description: Loose Screen

Let's finish with the Loose Screen and also a dynamic value:

The first input value is this one:

Oh no, you didn't find the _Mystery Number_ in 10 attempts.

The number was **$1**!

Don't worry, you can try again ;-)

Practice Conclusion

This practice section was a bit more directed than the previous ones. Since it's mainly UI there is not much thing going on! However my design is purely personal, don't hesitate to play around and create your own design 😉 As long as you keep the properties and events, the UI itself is secondary.

This is the running app, I just do a loop Home>Play>Win in my on action clicked:

The game is starting to take shape 😃
All that missing is the actual logic of the game, and we will add it right in the next chapter!