So now that we've managed to create our new Internet computer decentralised app and we've managed to 1
get the frontend linked up and working, then it's time to actually make sure that we can persist the 2
data that the user types in and figure out how we're going to do our backend using Motoko. 3
Now if you didn't manage to get this working, don't continue. 4
Make sure that you go back to the previous lesson and get it actually up and running because none of 5
the things that we're going to be doing now is going to help this. 6
So if you don't see this running on your local host, go back to the previous lesson and try again from 7
the beginning. 8
You might have missed out something somewhere that's actually causing your problem. 9
But if you're seeing what I'm seeing and you managed to get the keeper app running on local host with 10
the frontend actually functioning, then we can proceed to the next step. 11
Coming back to our code, we're going to close down some of these files and go into our main.mo. 12
Now inside this, you've got the Hello world code, which is just there from the template, so we can 13
delete it entirely. 14
And let's go ahead and create our actor, which is our canister, again from scratch. 15
So I'm going to call dkeeper. 16
I'm just adding D to all the decentralized apps that we're creating, but keep the naming that I've 17
got just so that when we do issue commands and stuff, we're all using the same thing and we're not 18
getting confused by some of these naming things. 19
When you create your own custom projects later on, feel free to name it whatever you want. 20
But for now, just continue and use the terrible names I come up with. Inside our new actor 21
we're going to create a new data type. 22
This data type is going to be of type Note and this is basically the way that we create a new data type 23
to represent the kind of data that will be stored in each of these notes. 24
And as you can see, it's just the title and some content. 25
So this data type is going to be pretty simple as well. 26
So you're going to write the type keyword and then Note, and then we're going to use an equal sign 27
and open up a set of curly braces. 28
Now we'll get to add the components that make up a note. 29
So it's going to be a title, which is going to be of type text and some content, which is also going 30
to be of type text. 31
Cut those off with some semicolons and now we've got a new data type created in Motoko. 32
The syntax can be a little weird. 33
It's a little bit different from JavaScript how we would create new objects, but it's not too big a 34
difference and you can pretty much see what's going on here because we need to access this type from 35
the JavaScript side as well, 36
it's a good idea to add the public keyword to the front of it. 37
This way when we're writing our code in our index.js or inside our components, then we'll actually 38
be able to see this data type and be able to use it there as well. 39
Now next, we're going to create our new variable, which is going to be called notes. 40
And this variable is going to have a data type of a list, which is kind of similar to the arrays that 41
we've been working with in JavaScript, but also a little bit different. 42
And I'll point out the differences later on. 43
Now the list is going to contain note type. 44
So to specify that in this data type, we have to write a list, .list, and then open up some angle 45
brackets and say that it will contain note objects inside this list. 46
Now we're going to start it off as a empty list for now, 47
so we'll just say List.nil and again, specify that it is going to be nil, but it's a nil note 48
object and then we add a set of parentheses and this will create a new list object. 49
Now you'll see a red underline here saying unbound variable list 50
and this is because in order to use some of its functionality, 51
so if we use list dot something, we're no longer using it as a type, but we're using some of its methods. 52
So we have to import it basically. 53
So we can just copy that and then say import list from the Motoko base library and the list module and 54
now you can see those errors disappear. 55
So here we've basically created the equivalent of an array of note objects, but in this case, it's 56
actually a list that contains objects 57
of type note. 58
Now we're going to create our public function and our function is going to be called createNote and 59
it's going to allow us to send over some titleText from the JavaScript side when the user enters it 60
into the text field and also send over some contentText. 61
And once we've gotten hold of that, then we can create a new note so we can say let new note be of 62
type note. 63
And we can use the equal = { to set it. 64
So we're going to set the title attribute to equal, 65
so notice here we've got equal when we're creating the new note. 66
And here when we're declaring the type, we've got the semicolon to specify the data type. 67
So a little bit different, 68
just be careful. 69
And we're going to set the title attribute to the titleText that was sent over 70
and the content attribute is going to equal the contentText that gets sent over. 71
And now here we've created our new note from whatever data was added to the input when this method was 72
called from the JavaScript side. 73
And finally, what we have to do is to add this new note to this list of notes. 74
And if we take a look in the dfinity documentation and we go to this list type, you can see that 75
we've used the nil to create an empty list. 76
And we're now going to use the push to add the new note to the list. 77
And you can see it happens by pre-pending a value. 78
So it's going to get added to the beginning of the list. 79
And this is a little bit different from how we add to arrays normally where we normally append it, 80
so we add it to the end. 81
And this is going to come in as very important a little bit later on when we try to organize our various 82
notes inside the keeper app. 83
So we're using this push and in order to push an item onto the list, we have to specify two things. 84
One is the item that is going to be pushed into the list, and second is the list that you want to push 85
it on. 86
So this is actually a function from the list module. In order to call it 87
we have to first tap into the list module and then use .push and then open up our parentheses and 88
add the first item. 89
The new note is going to be pushed onto the list and then comma, 90
and the list that we want to push it into is the notes list. 91
And let's just add some semicolons so that we make these errors go away. 92
Now, in this case, what we've done with this line of code is we've basically created a new list that 93
adds this new note to the beginning of the list of notes. 94
We haven't actually amended this list at all. 95
So in order to actually set this as the value, the new value of this list of notes, we have to use 96
that assign operator. 97
So we have to say notes colon equals the new list that's created from this function. 98
And once we've done that, let's go ahead and add a debug into this. 99
So let's import the debug library. 100
And use debug.print and then debug_show in order to print out what the notes list actually looks 101
like at this point. 102
So this is all that we have to do in our main.mo file in order to create a new note. 103
So notice we're basically doing CRUD here, right? 104
Create, read, update and delete. 105
And we were doing this whenever we built backends using MongoDB, adding new items to the database, 106
reading from the database and all of that. 107
So this is a really, really good example to get your head around how CRUD works using Motoko on the 108
ICP Blockchain. 109
So we've created it our Motoko file, but we have to link it up with our JavaScript. And where most of 110
the action is happening on the JavaScript side is inside the app.jsx. 111
So if you open it up, you can see there's a function called addNote which gets triggered every time 112
the user presses this add button. 113
And that's because we created that component called CreateArea, which is basically this area, 114
and we have an event listener on that add button so that when that happens, we trigger this function add 115
note. 116
And we went into this in a lot of detail when we learned about React. 117
So I'm not going to go into this too much. 118
If you want a quick review, I again really strongly recommend that you take the React module before 119
you proceed so that everything makes more sense. 120
But if you have done the React module, then let's just plow on. 121
So this function is what we're going to have to modify a little bit in order to get this createNote 122
to be triggered and to pass it the things that it needs. 123
So in order to get hold of anything in the main.mo file, we have to import it into our jsx file. 124
So I'm going to say import, and then it's going to be a set of curly brackets, 125
and inside these curly brackets, I'm going to refer to the name of my canister which is going to 126
be to dkeeper. The canister name is specified in the dfx.json. 127
And because we created a new project called keeper, both the main folder and the canister are called 128
dkeeper. And the location is going to be from and then it's going to be ../.. 129
/../ declarations, and then it's going to be dkeeper folder. 130
And this relative path corresponds to-- every ../ is an exit, 131
so going up one level. 132
So here we've got three of these 133
so we're going up three levels. 134
So from the app.jsx into the source folder, from the source folder into the dkeeper assets and then 135
from here into this final level so that we're here. And then we go into the declarations folder and we 136
go into the dkeeper folder so that we can get access to all the things which are public in our main.mo. 137
Now at the moment, you'll only see the previous function from when we built this brand new Hello World 138
app, which contained that greet function. 139
But if we go ahead and run a dfx deploy, it will be able to create the required bridge to allow our 140
JavaScript code to call these Motoko functions. 141
And you can see that here. 142
We've now got our createNote that takes two text inputs and returns nothing. 143
So coming back here, we can then access it using our module name. 144
So inside the addNotes function, when we're triggering set notes basically to update the state of 145
our notes constant, 146
just before we return, we're going to call that function. 147
So we're going to say dkeeper.t and we're going to tap into that method name and it doesn't always 148
load it up for you. 149
So it might be worth just actually copying it from here or from here, 150
it doesn't really matter as long as you've got it spelt correctly. 151
And then we have to provide two arguments which both have to be strings. 152
And in JavaScript, we're going to have to make sure that the order that we add in the arguments matches 153
with the order that we created in our Motoko side. 154
So the first thing we add is the title and the next is the content. 155
So in here we're going to tap into this new note that's created on the frontend. 156
And we're going to tap into, firstly, its title, 157
and secondly, it's going to be the newNote.content. 158
And the reason why they have these attribute names is because in our createArea, we've defined how 159
the notes are structured and they've got two attributes: title and content. 160
So I'm just keeping it the same everywhere for consistency sake. 161
So in this case, we're tapping into the title and the content that gets created on the frontend, and 162
I'm sending that over via the createNote back over here so that we can create a new note on our back 163
end. 164
And with just those few lines of code, we should have now be able to get this to work. 165
What I'm expecting to happen is when I create a new note and I click add, not only does the frontend 166
update because I'm using the used state to update the notes constant to include the new note that was 167
created, 168
but also I'm expecting a print statement to occur somewhere in here to show that that new note has actually 169
been created on the back end and this list of notes has been updated. 170
So let's try it out. 171
So if you haven't already dfx deployed, go ahead and do that, because that's going to be really important 172
to make sure this code actually can be reachable. 173
And once you've done that, let's refresh our 174
Keeper app and let's write a new note, which I'll call Note1. 175
Let's hit add and you can see the frontend updates immediately because that's happening through React. 176
But the most important thing is to make sure our backend actually registered correctly and that this 177
debug statement actually got called. 178
And if you look in here, the terminal where you had the dfx start running, you should see that the canister, 179
so this to dbank canister, sent the message where it printed out what is currently inside this notes list 180
and it has the content of this and the title of this which matches exactly with what we typed in there. 181
Now we've managed to actually get our backend to work and to complete the C aspect of the CRUD, be 182
able to create new items on our back end and store that inside our list, which is called Notes. 183
Now in the next lesson, we're going to move on to the R of CRUD. 184
So we're going to be able to read from these notes and update them in here so that when we refresh it, 185
they don't disappear. 186
So for all of that and more, we'll see on the next lesson.