So in another thread I was asking about markdown editors and I was trying to setup a few tests using some of them.
I currently have a custom dialog input form setup that just uses a textarea for some content that I would like to have some text formatting options for the user, and I was trying to set a ref to that element to pass into the CKEditor. For some reason it wasn’t showing up. So i immediately thought, “What did I screw up?!”
I proceeded to create a code pen to make sure I was implementing it correctly and it worked there. (in a plain view, not dialog)
I then went back to my code, and created a test on a non-aurelia-dialog served page, and it worked there.
However for an aurelia-dialog served view template it appears its not setting ref type element bindings as its not available in the attached hook.
Is this expected behavior, a bug, I did screw up?
1 Like
I think it’s unclear what error / issue you ran into. I do things you mentioned too, and ref
works fine, so it would be great if you could provide an example / sandbox demo
1 Like
I used your hello world pen for the first test.
I am unsure how to setup aurelia-dialog there though.
Is that available someplace from a CDN (or is it already in the aurelia-script?
Actually not sure a pen is the best place to try that as I need separate files.
1 Like
So I found this gist.run: https://gist.run/?id=5abaa0a16e8ee3c01efed8f99a4c0d20
and just added a ref to one of the templates button, and used alert to display it in the attached hook. It appears to be working there.
The only difference is I am using typescript that I can see. Now to look to see if I can find something like this one using typescript.
1 Like
Just in case its something that is easily visible to the trained eye here are the view and viewmodel.
View
<template>
<style>
ux-dialog-overlay.active {
background-color: black;
opacity: .5;
}
ux-dialog-header {
border-radius: 6px 6px 0px 0px;
background-color: yellow;
padding: 3px;
}
.edit-news-title {
margin: 5px;
font-weight: bold;
}
.edit-news-item {
margin: 10px 10px 10px 40px;
}
.edit-news-input {
width: 50ch;
}
.edit-news-short-input {
width: 20ch;
}
.edit-news-largecheckbox {
margin-left: 4px;
transform: scale(2);
}
</style>
<ux-dialog with.bind="model">
<ux-dialog-header>Edit News Item #${id}</ux-dialog-header>
<ux-dialog-body style="height: 800px; overflow-y: scroll;">
<button class="btn btn-danger" click.trigger="delete()">Delete</button>
<!-- <div class="edit-news-title">Created On</div>
<div class="edit-news-item">${createdOn | dateFormat: "YYYY-MM-DD"}</div>
<div class="edit-news-title">Created By</div>
<div class="edit-news-item">${createdBy}</div> -->
<div class="edit-news-title">Never Expires</div>
<div class="edit-news-item">
<input class="edit-news-largecheckbox" type="checkbox" checked.bind="neverExpires">
</div>
<div class="edit-news-title">Start Date</div>
<div class="edit-news-item">
<input type="datetime-local" value.bind="startDate | dateToLocal: 'YYYY-MM-DDTHH:mm:ss'">
</div>
<div class="edit-news-title">End Date</div>
<div class="edit-news-item">
<input type="datetime-local" value.bind="endDate | dateToLocal: 'YYYY-MM-DDTHH:mm:ss'">
</div>
<div class="edit-news-title">IsActive</div>
<div class="edit-news-item">
<input class="edit-news-largecheckbox" type="checkbox" checked.bind="isActive">
</div>
<div class="edit-news-title">IsPublic</div>
<div class="edit-news-item">
<input class="edit-news-largecheckbox" type="checkbox" checked.bind="isPublic">
</div>
<div class="edit-news-title">IsPinned</div>
<div class="edit-news-item">
<input class="edit-news-largecheckbox" type="checkbox" checked.bind="isPinned">
</div>
<div class="edit-news-title">IsHighlight</div>
<div class="edit-news-item">
<input class="edit-news-largecheckbox" type="checkbox" checked.bind="isHighlight">
</div>
<div class="edit-news-title">Tags (Max 20 char)</div>
<div class="edit-news-item">
<input value.bind="tagInput" maxlength="20" class="edit-news-short-input"> <button click.trigger="addTag()">Add Tag</button>
<ul style="margin: 10px;">
<li style="width: 180px; height: 30px;" repeat.for="item of tags">${item} <button class="pull-right" click.trigger="removeTag($index)">Remove</button></li>
</ul>
</div>
<div class="edit-news-title">Title (Max 50 char)</div>
<div class="edit-news-item">
<input value.bind="title" maxlength="50" rows="10" class="edit-news-input">
</div>
<div class="edit-news-title">Content</div>
<div>
<textarea id="editor" ref="editor" value.bind="content"></textarea>
</div>
View
</ux-dialog-body>
<ux-dialog-footer>
<button click.trigger="cancel()">Cancel</button>
<button click.trigger="save()">Save</button>
</ux-dialog-footer>
</ux-dialog>
</template>
ViewModel
import { CommonDialogs } from 'resources/dialogs/common-dialogs';
import { inject } from 'aurelia-framework';
import { DialogController } from 'aurelia-dialog';
import { NewsEntry } from 'models/news-entry';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
@inject(DialogController)
export class EditNewsItem
{
model: NewsEntry;
tagInput: string;
tags: string[];
commonDialogs: CommonDialogs
editor: Element;
ViewModel
constructor(private dialogController: DialogController)
{
}
activate(model)
{
console.log(this.editor);
this.model = model.newsItem;
this.commonDialogs = model.commonDialogs;
this.tags = this.model.tags;
this.tagInput = "";
ClassicEditor.create(this.editor)
.then(editor =>
{
console.log(editor);
})
.catch(error =>
{
console.error(error);
});
}
ViewModel
addTag()
{
if(this.tagInput && this.tagInput.length > 3)
{
this.model.tags.push(this.tagInput);
this.tags = this.model.tags;
this.tagInput = "";
}
}
removeTag(index: number)
{
this.model.tags.splice(index, 1);
this.tags = this.model.tags;
}
cancel()
{
this.dialogController.cancel();
}
save()
{
this.dialogController.ok(this.model);
}
delete()
{
this.commonDialogs.showMessage("This will move the news item to the archive. Are you sure?", "Delete", ["Yes", "No"])
.whenClosed(response => {
if(response.wasCancelled) return;
this.model.isDeleted = true;
this.dialogController.ok(this.model);
});
}
}
1 Like
I see, if you question was why this.editor
resolves to undefined
in activate
, then the answer is it’s the expected behavior. ref
attribute will create a binding, that will resolve during bind()
lifecycle, activate
lifecycle is specific to composition and will be invoked before bind()
, thus it is undefined.
activate
can be understood as a step to prepare the necessary data for binding.
1 Like
Gah, I was right when I thought I was wrong! I just caught that myself.
To many freaking A’s…yeah, I scewed up with activate instead of attached.
Thanks for your time on this, I appreciate it. Now to go crawl into my hole again.
1 Like
One final note on this.
CKEditor would still not display its interface after I fixed the incorrect initialization inside activate by moving it into attached.
Process of elimination ended up showing that it does not like being inside a with.bind.
Removing the with.bind, or moving it outside that enclosing section finally displayed the interface and started working.