I'm building a SPA using the Hot Towel SPA template.
Here's my problem:
I have a view where I put the information related to a Venue (Name, Description, Address, etc.)
Associated with the Venue there are different Rooms with their own fields (Name, Description, Type, etc.)
I have a list of Rooms and a button "Add New Room".
When I hit the button, a modal dialog pops up, I fill the form with the requested information then I save. After the dialog is closed the list gets updated.
I am able to retrieve the information from the dialog, but I'm not able to trigger the validation rules if the fields are left blank.
Also the datacontext.HasChanges() returns always true.
Is it possible to use the modal dialog like any other view?
Here's part of the code I am using:
From Model.cs:
public class Venue
{
[Key]
public int VenueId { get; set; }
[Required(ErrorMessage = "Venue Name is required.")]
[Display(Name = "Venue Name")]
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Room> Fields { get; set; }
...
}
public class Room
{
[Key]
public int RoomId { get; set; }
[Required(ErrorMessage = "Name is required.")]
[Display(Name = "Name")]
public string Name { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public int VenueId { get; set; }
public virtual Venue Venue { get; set; }
...
}
From venuedetail.js:
define(['services/datacontext',
'services/model',
'durandal/plugins/router',
'durandal/system',
'durandal/app',
'services/logger',
'viewmodels/roommodal'],
function (datacontext, model, router, system, app, logger, roommodal) {
...
var addRoom = function () {
var newRoom= datacontext.manager.createEntity("Room");
roommodal.room = newRoom;
app.showModal(roommodal).then(function (response) {
if (response) {
}
return true;
});
};
...
From roommodal.js:
define(['durandal/app', 'services/datacontext', 'durandal/system', 'durandal/plugins/router', 'services/logger'],
function (app, datacontext, system, router, logger) {
var isSaving = ko.observable(false);
var room= ko.observable();
activate = function(routeData) {
return true;
};
hasChanges = ko.computed(function() {
return datacontext.hasChanges(); // Always true ?
});
canSave = ko.computed(function() {
return hasChanges() && !isSaving();
});
canDeactivate = function () {
return true;
};
var save = function(dialogResult) {
this.modal.close(dialogResult);
};
var cancel = function() {
this.modal.close(false);
};
var vm = {
activate: activate,
save: save,
canSave: canSave,
cancel: cancel,
canDeactivate: canDeactivate,
room: room,
hasChanges: hasChanges,
title: 'Add room'
};
return vm;
From roommodal.html:
<div class="messageBox">
<div class="modal-header">
<h3 data-bind="text: title"></h3>
<i class="icon-asterisk" data-bind="visible: hasChanges"></i>
</div>
<div class="modal-body">
<div data-bind="with: room">
<label for="name">Name</label>
<input id="name" data-bind="value: name, valueUpdate: 'afterkeydown'"
placeholder="Enter name" />
<div>
<label>Description</label>
<textarea data-bind="value: description"
placeholder="Enter description"></textarea>
</div>
<div>
<label>Notes</label>
<textarea data-bind="value: notes"
placeholder="Enter notes"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-info"
data-bind="click: cancel, enable: canSave">
<i class="icon-undo"></i>Cancel</button>
<button class="btn btn-info"
data-bind="click: save, enable: canSave">
<i class="icon-save"></i>Save</button>
</div>
Any help will be greatly appreciated. Thanks in advance.
Validation is triggered when you try to save using datacontext.saveChanges()
which you don't do in this piece of code, instead, you are just closing the modal window.
Easiest way to see if saving was successful is to check HasChanges
afterwards - it should be false if everything went well, otherwise it will be true.
datacontext.HasChanges()
returns true when you enter modal window because you create an entity and place it in your context before opening the modal window. You can only ignore HasChanges
and silently CancelChanges
before closing the modal window.