In a chat component's scope, we will use the Message model to
save new messages and observe changes to the Model.
new Message.List({}) is a shortcut to perform
the findAll operation on a can.Model and
return a can.List.
...
scope: {
messages: new Message.List({}),
newMessage: ""
...
The tabs Component used can-click to listen for click events.
Since this chat application uses a <form> for sending messages, we’ll use
can-submit to specify an event handler.
There’s one more helper used in the template: can-value.
This automatically two-way binds the value of an input field to an observable
property on the scope of the component (in this case, newMessage).
When submitMessage is called, a new Message is created
with new Message(). Since can-value was declared on the input element, newMessage will
always be the current text in the input field.
The body of the message is fetched from
the Component's newMessage attribute when a user submits the form.
To save the new message to the server, call save().
submitMessage: function(scope, el, ev){
ev.preventDefault();
new Message({body: this.attr("newMessage")}).save();
this.attr("newMessage", "");
}
Finally, when a new Message is created, the messages list
must be updated.
There are two ways that messages are added: from the current user,
or from another user. In the next section, we demonstrate how to use
socket.io to update the Message model with messages
from other users in real time. Binding to the created event for all
messages allows us to create a single entry point that pushes new messages
to the scope, regardless of where those messages are from.
When the chat Component is loaded, messages are loaded from the server
using can.Model and new Message.List({}). When a new message is
submitted:
submitMessage is called via the event handler bound by the can-submit attribute
a new Message is created and saved to the server
'{Message} created' detects this change and adds the new message to messages
The template is automatically updated since messages is an observable can.List
Add real-time functionality
This example uses socket.io
to enable real-time functionality. This guide won't go
into detail on how to use socket.io, but for real-time
chat the application needs two more things.
When a message is created on another chat client, socket.io
will notify this client by triggering the message-created event,
wich will render the new message in the page by adding it to the
Message model.
var socket = io.connect(myServerUrl);
socket.on('message-created', function(message){
new Message(message).created();
});
To keep the created event from firing
twice, we modify the create function in the model.
If there was simply a return statement, Model would
create and fire a create event, which socket is already
doing. By returning a Deferred, we prevent firing of
one of these events.
In CanJS,
can.Modeladds functionality tocan.Mapto work with data on a server. It enables you to:can.Modelallows you to access data from a server easily:Using any server with a REST interface,
can.Modelenables create, read, update, and destroy functionality.Create a Chat Application
To put together a chat application, we’ll use two methods from
can.Modelto fetch the messages and create new ones:In a chat component's scope, we will use the
Messagemodel to save new messages and observe changes to the Model.new Message.List({})is a shortcut to perform thefindAlloperation on acan.Modeland return acan.List.The tabs Component used
can-clickto listen for click events. Since this chat application uses a<form>for sending messages, we’ll usecan-submitto specify an event handler.There’s one more helper used in the template:
can-value. This automatically two-way binds the value of an input field to an observable property on thescopeof the component (in this case,newMessage).When
submitMessageis called, a newMessageis created withnew Message(). Sincecan-valuewas declared on theinputelement,newMessagewill always be the current text in theinputfield. The body of the message is fetched from the Component'snewMessageattribute when a user submits the form.To save the new message to the server, call
save().Finally, when a new
Messageis created, themessageslist must be updated.There are two ways that messages are added: from the current user, or from another user. In the next section, we demonstrate how to use socket.io to update the
Messagemodel with messages from other users in real time. Binding to thecreatedevent for all messages allows us to create a single entry point that pushes new messages to thescope, regardless of where those messages are from.When the chat Component is loaded, messages are loaded from the server using
can.Modelandnew Message.List({}). When a new message is submitted:submitMessageis called via the event handler bound by thecan-submitattributeMessageis created and saved to the server'{Message} created'detects this change and adds the new message tomessagesmessagesis an observablecan.ListAdd real-time functionality
This example uses socket.io to enable real-time functionality. This guide won't go into detail on how to use
socket.io, but for real-time chat the application needs two more things.When a message is created on another chat client,
socket.iowill notify this client by triggering themessage-createdevent, wich will render the new message in the page by adding it to theMessagemodel.To keep the
createdevent from firing twice, we modify thecreatefunction in the model. If there was simply areturnstatement,Modelwould create and fire acreateevent, whichsocketis already doing. By returning aDeferred, we prevent firing of one of these events.