javascript で複雑なフォームをコーディングする最も効率的で安全でスマートな方法について疑問に思っています。
多くの場合、ユーザー フォームはさまざまな状態や複雑なチェックなどで非常に複雑になる可能性があり、適切な作業を行うには優れたコンセプトが絶対に必要です。
最善の解決策はステート マシンだと本当に信じています。
次のコードは、RFID タグ キーを使用したユーザー登録のために私が行ったフォーム コア ロジックです。ユーザーは、電話、キー RFID タグ、メールなどのさまざまな資格情報を使用して自分自身を登録し、後の段階で同じフォーラムで登録を完了することができます。その背後にあるロジックだけを大まかに考えてみてください。
可能な遷移を反復するメイン ループ (優先度順):
/* Evaluate the actual form state (status) and check if it's possible to change
* to another status with a greater priority.
* If the state transition conditions are verified the transition callback is executed
* which, in case the state doesn't, is an empty function.
*/
setNextFormStatus: function(field) {
var sts,
that = this;
function conditionsAreValid(sts) {
var context = that.statusToConditionsMap[sts];
return ( sts == 'new_account' || that[context.field].state == context.state );
}
for (sts in this.statusToConditionsMap[this.status.actual].changes) {
var transition = this.statusToConditionsMap[this.status.actual].changes[sts];
if (transition && conditionsAreValid(sts)) {
if (sts != this.status.actual) {
this.status.previous = this.status.actual;
this.status.actual = sts;
this._resetForm(); // simple reset function
transition.apply(this);
}
break;
}
}
}
すべてのステータス、それらの遷移条件、およびそれらの遷移コールバックは、ステータスが優先度順にリストされている場合にディクショナリで定義されます。
/*
* This is the dictionary which defines form status states machine
*
* For each status are defined the following attributes:
* · state & field: define the condition to enter this status. The field must have that state (i.e. field.state == state)
* · changes (optional): the list of possible next status from this one, ordered by priority. Each status has an handle to call
*/
this.statusToConditionsMap = {
'registered_key':{
state: 'registered',
field: 'key'
},
'processed_key_with_username':{
state: 'unlinked',
field: 'key',
changes: {
'processed_key_with_username': function() {}, // empty cause callback is unnecessary
'new_account': this._checkNotEmptyFields
}
},
'phone_already_present_confirmed':{
state: 'already_present_confirmed',
field: 'phone',
changes: {
'phone_already_present_confirmed': function() {},
'phone_already_present_unconfirmed': this.phone_already_present_unconf_data_filler,
'new_account': this._checkNotEmptyFields
}
},
'phone_already_present_unconfirmed':{
state: 'already_present_unconfirmed',
field: 'phone',
changes: {
'phone_already_present_confirmed': this.phone_already_present_data_filler,
'phone_already_present_unconfirmed': function() {},
'new_account': this._checkNotEmptyFields
}
},
'email_already_present':{
state: 'email_already_present',
field: 'email',
changes: {
'phone_already_present_confirmed': this.phone_already_present_data_filler,
'phone_already_present_unconfirmed': this.phone_already_present_unconf_data_filler,
'email_already_present': function() {},
'new_account': this._checkNotEmptyFields
}
},
'new_account':{
state:'',
field: '',
changes: {
'registered_key': this.registered_key_data_filler,
'processed_key_with_username': this.processed_desikey_data_filler,
'phone_already_present_confirmed': this.phone_already_present_data_filler,
'phone_already_present_unconfirmed': this.phone_already_present_unconf_data_filler,
'email_already_present': function() {this.showMailCheckbox(); this.runCheck('phone');},
'new_account': function() {}
}
}
}
複雑なフォームを実装するためのベスト プラクティスはどれですか?
他の解決策または方法は高く評価されます。