在前端的业务中不能避免要使用动态的表单,必须在表单的很多项目是基于配置,根据动态的配置,再前端进行表单生成
基础组件类:
1 class Component { 2 constructor(type) { 3 this.type = type; 4 this.label_tpl = '<label class="col-sm-2 control-label col-lg-3" title="{1}">{0}</label><div class="col-lg-7">{2}</div>'; 5 } 6 7 static setAdapter(adapter) { 8 if (!adapter.opts) { 9 alert("error: adapter.opts() method not exists."); 10 } 11 Component.adapter = adapter; 12 } 13 14 packing(opts, input) { 15 if (opts.hasOwnProperty('nopack')) { 16 return input; 17 } 18 19 if (opts.helper) { 20 input += '<span class="help-block text-primary">' + opts.tips + '</span>'; 21 } 22 let title = opts.hasOwnProperty('color')? '<font color="#'+opts.color+'">'+opts.title+'</font>' : opts.title; 23 input = this.label_tpl.format(title, opts.tips, input); 24 25 return '<div class="form-group">'+ input + '</div>'; 26 } 27 28 static factory(type) { 29 if (!Component.components.hasOwnProperty(type)) { 30 let o = null; 31 switch(type) { 32 case 'none': 33 o = new None; 34 break; 35 case 'indent': 36 o = new Indent; 37 break; 38 case 'text': 39 o = new InputText; 40 break; 41 case 'radio': 42 o = new InputRadio; 43 break; 44 case 'select': 45 o = new InputSelect; 46 break; 47 case 'checkbox': 48 o = new InputCheckbox; 49 break; 50 case 'checkboxs': 51 o = new InputCheckboxs; 52 break; 53 default : 54 console.log("error: input-" + type + ' not exists.'); 55 return null; 56 } 57 Component.components[type] = o; 58 } 59 return Component.components[type]; 60 } 61 62 addInitCallbacks(id, callback) { 63 if ( typeof callback === 'string') { 64 callback = eval(callback); 65 } 66 67 Component.init_callbacks[id] = callback.bind(id); 68 } 69 70 // process opts 71 _opts(opts) { 72 if (opts.hasOwnProperty('inited')) { 73 return opts.inited; 74 } 75 76 if (Component.adapter) { 77 Component.adapter.opts(opts); 78 } 79 80 if (opts.input != 'none' && !opts.hasOwnProperty('name')) { 81 alert(this.type + " opts.name not exists"); 82 opts.inited = false; 83 return false; 84 } 85 86 if (this.type == 'select' || this.type == 'radio') { 87 if (!opts.hasOwnProperty('dictionary')) { 88 alert(this.type + " opts.dictionary not exists"); 89 opts.inited = false; 90 return false; 91 } 92 } 93 opts.id = opts.id || opts.name; 94 opts.title = opts.title || opts.name; 95 opts.tips = opts.tips || opts.title; 96 opts.required = (opts.required == 1)? 'requried' : ''; 97 98 opts.onevent = ''; 99 if (opts.event && opts.func) { 100 opts.onevent = 'on' + opts.event + '="'+opts.func+'(this);"'; 101 } 102 103 if (typeof(opts.value) == "object" && opts.hasOwnProperty('value_idx')) { 104 opts.value = opts.value[opts.value_idx]; 105 } 106 opts.inited = true; 107 return true; 108 } 109 110 translate(name, value) { 111 if ( Component.dictionaries.hasOwnProperty(name) ) { 112 if ( Component.dictionaries[name][value]) { 113 return Component.dictionaries[name][value]; 114 } 115 } 116 return value; 117 } 118 119 setValue(opts, value) { 120 opts.value = value; 121 } 122 123 getValue(opts) { 124 opts.value = opts.value || opts.default; 125 if (opts.value_idx && typeof(opts.value) == 'object'){ 126 opts.value = opts.value[opts.value_idx]; 127 } 128 129 if (typeof(opts.value) == 'string' && opts.value != '' && opts.link_col != "") { 130 return this.translate(opts.link_col, opts.value); 131 } 132 133 return opts.value; 134 } 135 136 } 137 138 Component.adapter = null; 139 Component.components = {}; 140 Component.dictionaries = {};
常用的表单输入组件的实现:
1 class InputRadio extends Component { 2 constructor() { 3 super('radio'); 4 this.tpl = '<div class="checkbox-inline" style="padding-left:0px;margin-left:0px;"><input type="radio" value="{0}" id="{1}" name="{2}" class="{3}" {4} {5} /> {6}</div>'; 5 } 6 7 create(opts) {//, idx) { 8 if (false === this._opts(opts)) { 9 return ''; 10 } 11 let index = opts.index || 0; 12 let id = opts.id + index; 13 let name = opts.name + '[' +index+ ']'; 14 15 let input = ''; 16 Object.keys(opts.dictionary).map(key => { 17 let checked = (key == opts.value)? 'checked' : ''; 18 let tid = id + key; 19 input += this.tpl.format(key, tid, name, opts.required, checked, opts.onevent, opts.dictionary[key]); 20 if (opts.func && checked != '') { 21 this.addInitCallbacks(tid, opts.func); 22 } 23 }); 24 25 return this.packing(opts, input); 26 } 27 } 28 29 // 30 class InputCheckbox extends Component { 31 constructor() { 32 super('checkbox'); 33 this.tpl = '<div class="checkbox"><input type="checkbox" value="{0}" id="{1}" name="{2}" class="{3}" {4} {5} /></div>'; 34 } 35 36 create(opts) { 37 if (false === this._opts(opts)) { 38 return ''; 39 } 40 41 let value = this.getValue(opts); 42 if (value === 'false') { 43 value = 'true'; 44 } 45 let checked = opts.value == 'true'? 'checked' : ''; 46 let input = this.tpl.format(value, opts.id, opts.name, opts.required, checked, opts.onevent, opts.title, opts.tips); 47 48 return this.packing(opts, input); 49 } 50 } 51 52 class InputCheckboxs extends Component { 53 constructor() { 54 super('checkboxs'); 55 this.tpl = '<label class="checkbox-inline"><input type="checkbox" value="{0}" id="{1}" name="{2}" class="{3}" {4} {5} /> {6}</label>'; 56 } 57 58 create(opts) { 59 if (false === this._opts(opts)) { 60 return ''; 61 } 62 let index = opts.index || 0; 63 let id = opts.id + index; 64 let name = opts.name + '[' +index+ ']'; 65 66 let input = ''; 67 Object.keys(opts.dictionary).map(key => { 68 let checked = opts.value.find(v => v == key) == key? 'checked' : ''; 69 let tid = id + key; 70 input += this.tpl.format(key, tid, name, opts.required, checked, opts.onevent, opts.dictionary[key]); 71 if (opts.func && checked != '') { 72 this.addInitCallbacks(tid, opts.func); 73 } 74 }); 75 76 return this.packing(opts, input); 77 } 78 } 79 80 class InputText extends Component { 81 constructor() { 82 super('text'); 83 this.tpl = '<input type="text" value="{0}" id="{1}" name="{2}" class="{3} form-control input-sm m-bot15" {4} placeholder="{6}" title="{5}"/>'; 84 } 85 86 create(opts) { 87 if (false === this._opts(opts)) { 88 return ''; 89 } 90 91 let value = this.getValue(opts); 92 93 let input = this.tpl.format(value, opts.id, opts.name, opts.required, opts.onevent, opts.title, opts.tips); 94 95 return this.packing(opts, input); 96 } 97 } 98 99 class None extends Component { 100 constructor() { 101 super('none'); 102 this.tpl = '<label class="control-label" title="{1}">{0}</label>'; 103 } 104 105 create(opts) { 106 if (false === this._opts(opts)) { 107 return ''; 108 } 109 110 let value = this.getValue(opts); 111 112 let input = this.tpl.format(value, opts.tips); 113 114 return this.packing(opts, input); 115 } 116 } 117 118 class InputSelect extends Component { 119 constructor() { 120 super('select'); 121 this.tpl = '<select id="{0}" name="{0}" class="{1} form-control input-sm m-bot15" title="{3}" >{2}</select>'; 122 } 123 124 create(opts) { 125 if (false === this._opts(opts)) { 126 return ''; 127 } 128 129 let options = ''; 130 Object.keys(opts.dictionary).map(key => { 131 var selected = (key == opts.value)? "selected" : ""; 132 options += '<option value="'+key+'" '+selected+'>'+opts.dictionary[key]+'</option>'; 133 }); 134 135 let input = this.tpl.format(opts.name, opts.required, options, opts.tips); 136 137 return this.packing(opts, input); 138 } 139 }