数日間頭を悩ませている問題があります。おそらく私のサイトの小さな何か。
Reactive-mongo-coffeescript テンプレートから始めて、それを変更して、typesafe-reactive スタックを使用しようとしています。そこで、顧客の詳細を取得するようにメッセージ div を変更し、それを取得するようにバックエンドを変更しました。元のcoffeescriptコードを保持しました(おそらくそれが問題です...)。
コーヒースクリプト:
require(["webjars!knockout.js", 'webjars!jquery.js', "/routes.js", "webjars!bootstrap.js"], (ko) ->
messagesPerPage = 10
# Models for the customer page
class CustomerModel
constructor:() ->
self = @
# the messages field that first name is entered into
@firstNameField = ko.observable()
# the messages field that middle name is entered into
@midNameField = ko.observable()
# the messages field that last name is entered into
@lastNameField = ko.observable()
# the messages field that address line 1 is entered into
@addressOneField = ko.observable()
# the messages field that address line 2 is entered into
@addressTwoField = ko.observable()
# the messages field that address line 3 is entered into
@addressThreeField = ko.observable()
# the messages field that city is entered into
@cityField = ko.observable()
# the messages field that state is entered into
@stateField = ko.observable()
# the messages field that zip code is entered into
@zipField = ko.observable()
# the messages field that country is entered into
@countryField = ko.observable()
# the messages field that phone is entered into
@phoneField = ko.observable()
# the messages field that email is entered into
@emailField = ko.observable()
# save a new customer
@saveCustomer = () ->
alert("saving")
data: JSON.stringify({
firstName: @firstNameField()
midName: @midNameField()
lastName: @lastNameField()
addr1: @addressOneField()
addr2: @addressTwoField()
addr3: @addressThreeField()
city: @cityField()
state: @stateField()
zip: @zipField()
country: @countryField()
email: @emailField()
phone: @phoneField()
})
alert(data)
@ajax(routes.controllers.CustomerController.saveCustomer(), {
contentType: "application/json"
}).done(() ->
alert("done saving")
$("#addCustomerModal").modal("hide")
self.firstNameField(null)
)
# Models for the messages page
class MessagesModel
constructor: () ->
self = @
# the list of messages
@messages = ko.observableArray()
# the messages field that messages are entered into
@messageField = ko.observable()
# the URL to fetch the next page of messages, if one exists
@nextMessagesUrl = ko.observable()
# the URL to fetch the previous page of messages, if one exists
@prevMessagesUrl = ko.observable()
# save a new message
@saveMessage = () ->
@ajax(routes.controllers.MessageController.saveMessage(), {
data: JSON.stringify({
message: @messageField()
})
contentType: "application/json"
}).done(() ->
$("#addMessageModal").modal("hide")
self.messageField(null)
)
# get the messages
@getMessages = () ->
@ajax(routes.controllers.MessageController.getMessages(0, messagesPerPage))
.done((data, status, xhr) ->
self.loadMessages(data, status, xhr)
)
# get the next page of messages
@nextMessages = () ->
if @nextMessagesUrl()
$.ajax({url: @nextMessagesUrl()}).done((data, status, xhr) ->
self.loadMessages(data, status, xhr)
)
# get the previous page of messages
@prevMessages = () ->
if @prevMessagesUrl()
$.ajax({url: @prevMessagesUrl()}).done((data, status, xhr) ->
self.loadMessages(data, status, xhr)
)
# Convenience ajax request function
ajax: (route, params) ->
$.ajax($.extend(params, route))
# Handle the messages response
loadMessages: (data, status, xhr) ->
@messages(data)
# Link handling for paging
link = xhr.getResponseHeader("Link")
if link
next = /.*<([^>]*)>; rel="next".*/.exec(link)
if next
@nextMessagesUrl(next[1])
else
@nextMessagesUrl(null)
prev = /.*<([^>]*)>; rel="prev".*/.exec(link)
if prev
@prevMessagesUrl(prev[1])
else
@prevMessagesUrl(null)
else
@nextMessagesUrl(null)
@prevMessagesUrl(null)
# Setup
# model = new MessagesModel
model = new CustomerModel
ko.applyBindings(model)
# Load messages data
# model.getMessages()
# Server Sent Events handling
events = new EventSource(routes.controllers.MainController.events().url)
events.addEventListener("message", (e) ->
# Only add the data to the list if we're on the first page
if model.prevMessagesUrl() == null
message = JSON.parse(e.data)
model.messages.unshift(message)
# Keep messages per page limit
if model.messages().length > messagesPerPage
model.messages.pop()
, false)
)
saveCustomer の最後にあるアラート(「保存」)がポップするので、そこに到達しますが、ajaxのdone()句のアラート(「保存を完了」)はそうではありません。これにより、問題はjson.stringifyにあると思われます.
顧客作成部門:
@* createCustomerDiv Template File *@
@(customer: Option[models.Customer])
<div class="modal fade" id="addMessageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>
@if(customer==None){
Create
} else {
Edit
}
Customer</h3>
</div>
<div class="accordion" id="accordion">
<form role="form">
<div class="accordion-group">
<div class="accordion-heading collapse in">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
<h3 align="middle"><label>Customer Name</label></h3>
</a>
</div>
<div id="collapseOne" class="accordion-body collapse in">
<div class="accordion-inner">
<div class="modal-body">
<div class="form-group">
<label for="firstNameField">First Name</label>
<input type="text" class="form-control" id="firstNameField" placeholder="Enter first name" data-bind="value: firstNameField"/>
<label for="midNameField">Middle Name</label>
<input type="text" class="form-control" id="midNameField" placeholder="Enter middle name" data-bind="value: midNameField"/>
<label for="lastNameField">Last Name</label>
<input type="text" class="form-control" id="lastNameField" placeholder="Enter last name" data-bind="value: lastNameField"/>
</div>
</div>
</div>
</div>
</div>
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">
<h3 align="middle"><label>Address</label></h3>
</a>
</div>
<div id="collapseTwo" class="accordion-body collapse">
<div class="accordion-inner">
<div class="modal-body">
<div class="form-group">
<label for="addressOneField">Address</label>
<input type="text" class="form-control" id="addressOneField" placeholder="address" data-bind="value: addressOneField"/>
<label for="addressTwoField">Address (optional)</label>
<input type="text" class="form-control" id="addressTwoField" placeholder="address" data-bind="value: addressTwoField"/>
<label for="addressThreeField">Address (optional)</label>
<input type="text" class="form-control" id="addressThreeField" placeholder="address" data-bind="value: addressThreeField"/>
<label for="cityField">city</label>
<input type="text" class="form-control" id="cityField" placeholder="city" data-bind="value: cityField"/>
<label for="stateField">State</label>
<input type="text" class="form-control" id="stateField" placeholder="state" data-bind="value: stateField"/>
<label for="zipField">Zip code</label>
<input type="text" class="form-control" id="zipField" placeholder="zip" data-bind="value: zipField"/>
<label for="countryField">Country</label>
<input type="text" class="form-control" id="countryField" placeholder="country" data-bind="value: countryField"/>
</div>
</div>
</div>
</div>
</div>
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapseThree">
<h3 align="middle"><label>Communication</label></h3>
</a>
</div>
<div id="collapseThree" class="accordion-body collapse">
<div class="accordion-inner">
<div class="modal-body">
<div class="form-group">
<label for="emailField">Email</label>
<input type="email" class="form-control" id="emailField" placeholder="email" data-bind="value: emailField"/>
<label for="phoneField">Phone</label>
<input type="text" class="form-control" id="phoneField" placeholder="phone" data-bind="value: phoneField"/>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-link" data-dismiss="modal">Close</button>
<button class="btn btn-primary" data-bind="click: saveCustomer">Add customer</button>
</div>
</div>
</div>
</div>
最後に、ハンドラー メソッドです。ロガーは何もログに記録していないため、ここでは呼び出しが送信されていないと想定しています。
/**
* The customer form. This is separate from the database customer since the form doesn't have an ID.
*/
case class CustomerForm(
firstName: String,
midName: Option[String],
lastName: String,
addr1: String,
addr2: Option[String],
addr3: Option[String],
city: String,
state: String,
zip: String,
country: String,
email: String,
phone: String
) {
val name = Name(firstName, midName, lastName)
val eml = Email(email)
val cntry = Country(country)
val address = Address(BSONObjectID.generate, addr1, addr2, addr3, city, state, zip, cntry)
val phn = Phone(1,2,3)
def toCustomer: Customer = Customer(BSONObjectID.generate, name, eml, phn, address)
}
implicit val customerFormFormat = Json.format[CustomerForm]
/** Action to save a message */
def saveCustomer = Action(parse.json) { req =>
Logger.debug("saveCustomer called")
Json.fromJson[CustomerForm](req.body).fold(
invalid => BadRequest("Bad message form"),
form => Async {
CustomerDao.save(form.toCustomer).map(_ => Created)
}
)
}
}
どんな洞察も役立ちます。ありがとう。