I'm migrating from KnockoutJS to Aurelia and having a hard time trying to figure out how I can swap out some HTML/JS from a view. I have some existing Knockout code as follows:
$.ajax({
url: "/admin/configuration/settings/get-editor-ui/" + replaceAll(self.type(), ".", "-"),
type: "GET",
dataType: "json",
async: false
})
.done(function (json) {
// Clean up from previously injected html/scripts
if (typeof cleanUp == 'function') {
cleanUp(self);
}
// Remove Old Scripts
var oldScripts = $('script[data-settings-script="true"]');
if (oldScripts.length > 0) {
$.each(oldScripts, function () {
$(this).remove();
});
}
var elementToBind = $("#form-section")[0];
ko.cleanNode(elementToBind);
var result = $(json.content);
// Add new HTML
var content = $(result.filter('#settings-content')[0]);
var details = $('<div>').append(content.clone()).html();
$("#settings-details").html(details);
// Add new Scripts
var scripts = result.filter('script');
$.each(scripts, function () {
var script = $(this);
script.attr("data-settings-script", "true");//for some reason, .data("block-script", "true") doesn't work here
script.appendTo('body');
});
// Update Bindings
// Ensure the function exists before calling it...
if (typeof updateModel == 'function') {
var data = ko.toJS(ko.mapping.fromJSON(self.value()));
updateModel(self, data);
ko.applyBindings(self, elementToBind);
}
//self.validator.resetForm();
switchSection($("#form-section"));
})
.fail(function (jqXHR, textStatus, errorThrown) {
$.notify(self.translations.getRecordError, "error");
console.log(textStatus + ': ' + errorThrown);
});
In the above code, the self.type()
being passed to the url for an AJAX request is the name of some settings. Here is an example of some settings:
public class DateTimeSettings : ISettings
{
public string DefaultTimeZoneId { get; set; }
public bool AllowUsersToSetTimeZone { get; set; }
#region ISettings Members
public string Name => "Date/Time Settings";
public string EditorTemplatePath => "Framework.Web.Views.Shared.EditorTemplates.DateTimeSettings.cshtml";
#endregion ISettings Members
}
I use that EditorTemplatePath
property to render that view and return it in the AJAX request. An example settings view is as follows:
@using Framework.Web
@using Framework.Web.Configuration
@inject Microsoft.Extensions.Localization.IStringLocalizer T
@model DateTimeSettings
<div id="settings-content">
<div class="form-group">
@Html.LabelFor(m => m.DefaultTimeZoneId)
@Html.TextBoxFor(m => m.DefaultTimeZoneId, new { @class = "form-control", data_bind = "value: defaultTimeZoneId" })
@Html.ValidationMessageFor(m => m.DefaultTimeZoneId)
</div>
<div class="checkbox">
<label>
@Html.CheckBoxFor(m => m.AllowUsersToSetTimeZone, new { data_bind = "checked: allowUsersToSetTimeZone" }) @T[FrameworkWebLocalizableStrings.Settings.DateTime.AllowUsersToSetTimeZone]
</label>
</div>
</div>
<script type="text/javascript">
function updateModel(viewModel, data) {
viewModel.defaultTimeZoneId = ko.observable("");
viewModel.allowUsersToSetTimeZone = ko.observable(false);
if (data) {
if (data.DefaultTimeZoneId) {
viewModel.defaultTimeZoneId(data.DefaultTimeZoneId);
}
if (data.AllowUsersToSetTimeZone) {
viewModel.allowUsersToSetTimeZone(data.AllowUsersToSetTimeZone);
}
}
};
function cleanUp(viewModel) {
delete viewModel.defaultTimeZoneId;
delete viewModel.allowUsersToSetTimeZone;
}
function onBeforeSave(viewModel) {
var data = {
DefaultTimeZoneId: viewModel.defaultTimeZoneId(),
AllowUsersToSetTimeZone: viewModel.allowUsersToSetTimeZone()
};
viewModel.value(ko.mapping.toJSON(data));
};
</script>
Now if you go back to the AJAX request and see what I am doing there, it should make more sense. There is a <div>
where I am injecting this HTML, as follows:
<div id="settings-details"></div>
I am trying to figure out how to do this in Aurelia. I see that I can use Aurelia's templatingEngine.enhance({ element: elementToBind, bindingContext: this });
instead of Knockout's ko.applyBindings(self, elementToBind);
so I think that should bind the new properties to the view model. However, I don't know what to do about the scripts from the settings editor templates. I suppose I can try keeping the same logic I already have (using jQuery to add/remove scripts, etc)... but I am hoping there is a cleaner/more elegant solution to this with Aurelia. I looked at slots
, but I don't think that's applicable here, though I may be wrong.