Hi all,
I wanted to add a chat system into my project and have set up a text file creation for the logs, pushing the messages with username, time and message, and loading the logs from file when the chat is opened. I made a form component for the chat bubble, and the main form has a list formcomponent container on it with the contained form set to the chat bubble form component but I’m not sure where to go from here. Does anyone know how to dynamically add extra chat bubbles to the list form container in runtime?
Here is my current code:
function loadChat(fileContent) {
var lines = fileContent.split('\n');
chatLogsArray = [];
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
var match = line.match(/^(.*?) (\d{2}:\d{2}:\d{2}) - (.*)$/);
if (match) {
var user = match[1];
var time = match[2];
var message = match[3];
chatLogsArray.push({ user: user, time: time, message: message });
}
}
application.output(chatLogsArray);
populateChatList();
}
function populateChatList() {
for (var i = 0; i < chatLogsArray.length; i++) {
var chatEntry = chatLogsArray[i];
var chatComponent = createAndConfigureChatComponent(chatEntry);
addChatComponentToList(chatComponent);
}
}
I currently don’t have a function set up for either the createAndConfigureChatComponent(chatEntry) or the addChatComponentToList(chatComponent).
Thanks!
Alasdair
Hi Alasdair,
Question: from your previous posts I know you’re using NG client, thus browser.
The browser won’t be able to read files directly, so how are you seeing this text file to work?
Why not using a database, using a database you can also use the data broadcast event to trigger the chat update
In order to display messages you also might want to have a look at the customrenderer component.
You can just push data into the component and rendering will be done client-side using a render template (which you of course need to provide to the component)
Hi Marc,
Currently I’m creating a reading the txt file just using the file plugin, and it seems to be working both in local runtime and when running on a server.
var chatLog = scopes.global.chatLog()
var previousChatLog = plugins.file.readTXTFile(chatLog)
Thats a good point though, wasn’t sure how I was going to get around that. I’ll change the solution to use a database.
By customrenderer component do you mean the custom list?
alasdairs:
Currently I’m creating a reading the txt file just using the file plugin, and it seems to be working both in local runtime and when running on a server.
Correct it does, but the file is then read from the server.
Often developer find this ‘read file’ works perfectly in developer using a browser based client, but don’t realise it’s actually a serverside process (file plugin = java = server)
alasdairs:
By customrenderer component do you mean the custom list?
Yes, awesome component ![Smile :-)]()
Brilliant, Thanks!
Could the custom lists render template be the ‘chat bubble’ form component? Not entirely sure where to start with this component.
I need to be able to change the style classes of each of the entries or chat bubbles pushed to the list, depending on who sent them.
Through code you can add entries to the component.
Each entry is an object with the data for that particular entry.
Data can be anything: text you want to show, the type of entry or the style classes
You will also need a render function, which could look like this:
function onRender(entry) {
var _html += '\
<div class="list-row">\
<div class="list-cell-icon"><i class="fa-light fa-calendar-lines"></i></div>\
<div class="list-cell-container"> \
<div class="list-text-primary">' + entry.date + '<span class="plan-user">' + entry.user + '</span></div>\
' + entry.description + ' \
</div>\
<div class="list-cell-chevron ' + entry.class + '"><i class="' + entry.icon + '"></i></div>\
</div>';
return _html;
The above function can be pasted as text into the dedicated property of the component, or you can do this through code in the onShow of the form, like this:
function setOnRender(_sFormName, _sFunctionName) {
var _jsForm = solutionModel.getForm(controller.getName());
var _sCode = _jsForm.getMethod('onRender').code.replace(/\s\* @properties?[^}]+(}\n|$)/g, '');
return _sCode;
}
function onShow(firstShow, event) {
elements.list.entryRendererFunction = setOnRender();
}
As you will find, there’s also an entryStyleClassFunction property, that will process a function similar to the above, but then just returning the style class(es) as a string.
This can be nice to separate things, but passing in classes as per my example also works fine.
The above should get you started I guess.
One important thing to mention is that the code in the onRender function will completely run browser side.
This means it does not know anything about Servoy, therefore any code should just be plain javascript.
Tip: if you need to display dates, you can already set the formatted string into the entry objects by using a Servoy function.
Another thing: if you are going to use a database you can also use the foundset list.
This works in a similar way, just not an object but mapping of dataproviders.
Hope this helps
Thanks a bunch, got it working now! Had a bunch of trouble getting the onRender function working last night.
Ended up putting all the style classes into the onRender function in the end.
function renderChatEntry(entry) {
if (entry) {
var html = '<span class="' + entry.newMessageStyle + '">New Messages</span>' +
'<span class="chat-time">' + entry.displayTime + '</span>' +
'<span class="chat-user">' + entry.vuser + '</span>' +
'<div class="chat-message ' + entry.styleClass + '">' + entry.vmessage + '</div>' +
'</div>';
return html;
}
}
Thanks for all the help!
Great, looks good!
I see you got some good fatherly advice there in the chat ![Wink ;-)]()
Hi Alasdair,
Are you able to scroll to the bottom of the chat, from code?
I chose aggrid for my chat because I could not do this using the customlist component.
Thanks,
Diana
Hi Diana,
I think I got it to load the chat upwards instead of scolling to the bottom.
I recommend using the customlist component if possible, because it feels like it was made for something like this and I can help if you have any questions for it. It’s built with dynamic html on load, so you can pass in things like whether the person is you or someone else and the styles for each of them. It’s basically like a datagrid made out of your own html.
Here’s my code:
function loadChat() {
foundset.sort('index asc')
foundset.loadAllRecords()
var entryArray = []
for (var i = 1; i <= foundset.getSize(); i++) {
var entry = getChatLogEntry(foundset.getRecord(i), i)
if (entry) {
entryArray.push(entry);
}
}
elements.chatList.setEntries(entryArray.reverse())
}
CSS:
.chat-view {
display: flex; // this and
flex-direction: column-reverse; // this specifically
overflow-y: auto;
max-height: 420px;
padding-bottom: 4px;
scrollbar-width: none;
-ms-overflow-style: none;
}
Not sure whether this would work for a datagrid but thats what I did.
Alasdair
Hi Alasdair,
Nice trick with the flex-direction: column-reverse ![Smile :)]()