Ao criar visualizações de formulário para modelos em um aplicativo Chaplin JS , é uma boa ideia aproveitar o poder do padrão Mediator Pub / Sub de Chaplin para o envio de seu formulário para renderizar erros de validação e servidor em suas visualizações de formulário.
Digamos que temos um modelo Party :
class Party extends Model
url: '/parties.json'
defaults:
ladies: 0
fellas: 4
celebrities: 0
validate: (attrs, options) ->
if attrs.ladies / attrs.fellas < 1
"Sausage fest"
e sua visualização de “edição” correspondente:
class PartyEditView extends View
templateName: 'parties/form'
autoRender: true
events:
"submit form": 'saveParty'
saveParty: (e) ->
e.preventDefault()
# Some method to get model attributes from view values goes here
@model.save(@model.attributes)
Então, digamos que nosso partido não passe na validação. Provavelmente queremos saber sobre isso, certo? Direito. Vamos primeiro fazer um modelo de erro simples e uma visão para ele:
class Error extends Model
defaults:
text: "Something went wrong"
class ErrorView extends View
templateName: 'error'
autoRender: true
autoAttach: true
Portanto, nosso PartyEditView deve fazer algo com esse lixo de erro quando algo der errado:
class PartyEditView extends View
templateName: 'parties/form'
autoRender: true
events:
"submit form": 'saveParty'
regions:
'.errors': 'errors'
initialize: ->
super
@error = false
# When the Party is invalid, do something:
@model.on "invalid", (model, error) =>
@renderError(error)
saveParty: (e) ->
e.preventDefault()
@error.dispose() if @error
# Some method to get model attributes from view values goes here
@model.save(@model.attributes)
@renderError: (error) ->
model = new Error({text: error})
@error = new ErrorView model: model, region: 'errors'
Portanto, agora, quando tentarmos salvar o modelo, o invalid
evento será acionado . Vinculamos um ouvinte a invalid
para disparar o renderError
método, o que cria um novo Error
modelo e uma visão para ele. A visão renderiza e se anexa automaticamente à errors
região, que definimos no regions
objeto da visão . Ótimo.
Mas e se ele passar em nossa validação de front-end e o servidor achar que ainda é uma festa muito chata? Precisamos de uma maneira de processar os erros que o servidor retorna.
Em primeiro lugar, vamos dar uma olhada em nosso PartyEditView
. O saveParty
método parece suspeito. Por que uma View se preocupa com a persistência do modelo? Devíamos mudar para outro lugar. O controlador parece um bom lugar para esse tipo de comportamento.@model.save
class PartiesController extends Controller
save: (model) ->
@model.save model.attributes
Mas como o controlador sabe quando deve salvar o modelo? O serviço Pub / Sub de Chaplin é extremamente útil em casos como este. Vamos fazer com que o view publique uma mensagem “save_party” que o controlador ouvirá.
class PartyEditView extends View
saveParty: (e) ->
e.preventDefault()
@error.dispose() if @error
# publish the save_party message and pass the model along
@publishEvent 'save_party', @model
class PartiesController extends Controller
initialize: ->
super
# Listen for word about any cool parties and fire the save method
@subscribeEvent 'save_party', @save
save: (model) ->
@model.save model.attributes,
success: (model,response) =>
alert 'Party was saved!'
@redirectTo '/'
error: (model, response) =>
# Fire the view's renderError method and pass it the server response
@view.renderError(response)
Normalmente, a resposta do servidor será um objeto, portanto, precisaremos modificar renderError
um pouco o método de nossa visualização para extrair algum texto útil para exibição. Eu tenho meu controlador Rails configurado para entregar full_messages na resposta:
render :json => @party.errors.full_messages, status: 422
Portanto, a fim de mostrar texto relevante para o usuário, vamos fazer algo parecido com isso em nosso PartyEditView
‘s renderError
método:
renderError: (error) ->
@error.dispose() if @error
if typeof error is 'object'
# Extract text from each error in server response
for error in $.parseJSON(error.responseText)
errorObj =
text: error
model = new Error(errorObj)
@error = new ErrorView model: model, region: 'errors'
else
# Display validation error, which is just a string
errorObj =
text: error
model = new Error(errorObj)
@error = new ErrorView model: model, region: 'errors'
Aí está. Validação de renderização automática e erros de servidor em sua visualização. O ideal é que você pegue essa funcionalidade e a inclua em um modelo de vista de base que pode ser estendido:
class ModelView extends View
initialize: ->
super
@error = false
@registerRegion '.form-errors', 'errors'
@subscribeEvent 'renderError', @renderError
@model.on "invalid", (model, error) =>
@renderError(error)
renderError: (error) ->
@error.dispose() if @error
if typeof error is 'object'
for error in $.parseJSON(error.responseText)
errorObj =
text: error
model = new Error(errorObj)
@error = new ErrorView model: model, region: 'errors'
else
errorObj =
text: error
model = new Error(errorObj)
@error = new ErrorView model: model, region: 'errors'
Em seguida, você pode ter erro de renderização em qualquer visualização que desejar, usando o @registerRegion
método para direcionar um contêiner para renderizar as visualizações em:
class PartyEditView extends ModelView
templateName: 'party/form'
autoRender: true
events:
"submit form": 'saveParty'
initialize: ->
super
@registerRegion '.party-errors', 'errors'
saveParty: (e) ->
e.preventDefault()
@error.dispose() if @error
@publishEvent 'save_party', @model
class NoiseViolationEditView extends ModelView
templateName: 'violation/form'
events:
"submit form": 'saveViolation'
initialize: ->
super
@registerRegion '.legal-errors', 'errors'
saveViolation: (e) ->
e.preventDefault()
@error.dispose() if @error
@publishEvent 'save_violation', @model