3
0
Fork 0

fix: add custom password+confirmation widget for Vue3 + Oruga

traditional widget does not work correctly with Oruga, since the
`value` attr of `<b-input>` component for some reason prevents user
from entering text.

this new widget "works" fine although does give less descriptive
validation error message, e.g. when password/confirm values do not
match.  but this seems better than the alternative, for now
This commit is contained in:
Lance Edgar 2025-08-03 13:00:08 -05:00
parent 34d7cf4311
commit e3c0a8d99e
4 changed files with 80 additions and 3 deletions

View file

@ -2,7 +2,7 @@
################################################################################
#
# wuttaweb -- Web App for Wutta Framework
# Copyright © 2024 Lance Edgar
# Copyright © 2024-2025 Lance Edgar
#
# This file is part of Wutta Framework.
#
@ -153,6 +153,21 @@ class WuttaCheckboxChoiceWidget(CheckboxChoiceWidget):
self.app = self.config.get_app()
class WuttaCheckedPasswordWidget(PasswordWidget):
"""
Custom widget for password+confirmation field.
This widget is used only for Vue 3 + Oruga, but is *not* used for
Vue 2 + Buefy.
This is a subclass of :class:`deform:deform.widget.PasswordWidget`
and uses these Deform templates:
* ``wutta_checked_password``
"""
template = 'wutta_checked_password'
class WuttaDateWidget(DateInputWidget):
"""
Custom widget for :class:`python:datetime.date` fields.

View file

@ -0,0 +1,8 @@
<div tal:omit-tag
tal:define="name name|field.name;
oid oid|field.oid;
vmodel vmodel|'modelData.'+oid;">
<wutta-checked-password name="${name}"
v-model="${vmodel}"
tal:attributes="attributes|field.widget.attributes|{};" />
</div>

View file

@ -3,6 +3,7 @@
${self.make_wutta_request_mixin()}
${self.make_wutta_autocomplete_component()}
${self.make_wutta_button_component()}
${self.make_wutta_checked_password_component()}
${self.make_wutta_datepicker_component()}
${self.make_wutta_timepicker_component()}
${self.make_wutta_filter_component()}
@ -300,6 +301,54 @@
</script>
</%def>
<%def name="make_wutta_checked_password_component()">
<script type="text/x-template" id="wutta-checked-password-template">
<div>
<b-input type="password"
placeholder="Password"
v-model="password"
@input="passwordUpdated"
expanded />
<b-input type="password"
placeholder="Confirm Password"
v-model="passwordConfirm"
@input="passwordConfirmUpdated"
expanded />
<input type="hidden" :name="name" :value="passwordFinal" />
</div>
</script>
<script>
const WuttaCheckedPassword = {
template: '#wutta-checked-password-template',
props: {
modelValue: null,
name: String,
},
data() {
return {
password: null,
passwordConfirm: null,
passwordFinal: null,
}
},
methods: {
passwordUpdated(val) {
this.passwordFinal = (val && this.passwordConfirm == val) ? val : null
this.$emit('update:modelValue', this.passwordFinal)
},
passwordConfirmUpdated(val) {
this.passwordFinal = (val && this.password == val) ? val : null
this.$emit('update:modelValue', this.passwordFinal)
},
},
}
Vue.component('wutta-checked-password', WuttaCheckedPassword)
<% request.register_component('wutta-checked-password', 'WuttaCheckedPassword') %>
</script>
</%def>
<%def name="make_wutta_datepicker_component()">
<script type="text/x-template" id="wutta-datepicker-template">
<b-datepicker :name="name"

View file

@ -2,7 +2,7 @@
################################################################################
#
# wuttaweb -- Web App for Wutta Framework
# Copyright © 2024 Lance Edgar
# Copyright © 2024-2025 Lance Edgar
#
# This file is part of Wutta Framework.
#
@ -177,6 +177,7 @@ class AuthView(View):
'form': form}
def change_password_make_schema(self):
""" """
schema = colander.Schema()
schema.add(colander.SchemaNode(
@ -185,10 +186,14 @@ class AuthView(View):
widget=widgets.PasswordWidget(),
validator=self.change_password_validate_current_password))
# nb. must use different widget for Vue 3 + Oruga
widget = (widgets.WuttaCheckedPasswordWidget()
if self.request.use_oruga
else widgets.CheckedPasswordWidget())
schema.add(colander.SchemaNode(
colander.String(),
name='new_password',
widget=widgets.CheckedPasswordWidget(),
widget=widget,
validator=self.change_password_validate_new_password))
return schema