关于嵌套表单我有这个棘手的问题。只是说我有以下型号:
我在员工模型中也有两种类型的员工,
managers
通过manager
模型中的employees
属性指定,boolean
。<%= f.simple_fields for :employees do |f| %>
<%= render 'employee_fields', :f => f %>
<% end %>
。
当我编辑每个餐馆的员工名单时,它是通过嵌套的形式,即:
<%= render 'manager_fields', :f => f %>.
我的问题:有没有办法根据员工的类型呈现不同的部分表格?例如,如果当前员工是经理,那么
<%= render 'staff_fields', :f => f %>.
否则,如果当前员工是员工,那么
jQuery(document).ready(function() {
jQuery('#submit').click(function() {
var options = {
'name': {
required: true
},
'email': {
required: true,
email: true
},
'number': {
required: true,
digits: true
},
'select': {
required: true
},
'select-multiple': {
required: true
},
'radio': {
required: true
},
'checkbox': {
required: true
},
'checkbox-single': {
required: true
},
'multiple-emails': {
required: true,
multipleEmails: true
}
};
if (customValidation(options)) {
alert('Form validated!');
} else {
alert('Form not validated!');
}
});
});
function customValidation(options, bindEvents) {
/***
Function is based on jQuery Validation Plugin v1.13.1 but doesn't require a <form> tag
Add custom validations in this function as required
Currently supported validations are:
Required - Field cannot be blank
Email - Validates an email address
Mutliple Emails - Validates mutliple email addresses
Number - Validates a decimal number
Digits - Validates digits only
Todo:
Equal To validation
Allow specifying parent element for Checkbox and Radio elements to apply an error class
Allow specifying custom error and success functions through function parameter and individual options
***/
var fieldsValid = true;
bindEvents = (typeof bindEvents === 'undefined') ? true : bindEvents;
var errorDiv = jQuery('#errorDiv');
jQuery.each(options, function(elementIdorName, rules) {
var element = (jQuery('#' + elementIdorName).length) ? jQuery('#' + elementIdorName) : jQuery('input[name=' + elementIdorName + ']:first');
var elementType = element.prop('type');
var elementName = element.prop('name');
var elementValid = true;
// First remove any validation errors
jQuery('.error-' + elementName).hide();
jQuery.each(rules, function(rule, ruleOption) {
// Required
if (rule == 'required' && ruleOption == true) {
// Select
if (elementType && (elementType.toLowerCase() === 'select' || elementType.toLowerCase() === 'select-one' || elementType.toLowerCase() === 'select-mulitple')) {
var val = element.val();
if (val && val.length > 0) {
// Do nothing
} else {
elementValid = false;
}
}
// Checkbox and Radio
if ((/radio|checkbox/i).test(elementType)) {
if (jQuery('input[name=' + elementName + ']:checked').length > 0) {
// Do nothing
} else {
elementValid = false;
}
}
// Text, Email, Number and Textarea
if (jQuery.trim(element.val()).length > 0) {
// Do nothing
} else {
elementValid = false;
}
if (!elementValid) {
fieldsValid = false;
if (jQuery('.error-' + elementName).length == 0) {
errorDiv.append('<div class="error-' + elementName + '">' + elementName + '</div>');
} else {
jQuery('.error-' + elementName).show();
}
}
}
// Email
if (rule == 'email' && ruleOption == true) {
if ((/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/).test(element.val())) {
// Do nothing
} else {
elementValid = false;
}
if (!elementValid) {
fieldsValid = false;
if (jQuery('.error-' + elementName).length == 0) {
errorDiv.append('<div class="error-' + elementName + '">' + elementName + '</div>');
} else {
jQuery('.error-' + elementName).show();
}
}
}
// Number
if (rule == 'number' && ruleOption == true) {
if ((/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/).test(element.val())) {
// Do nothing
} else {
elementValid = false;
}
if (!elementValid) {
fieldsValid = false;
if (jQuery('.error-' + elementName).length == 0) {
errorDiv.append('<div class="error-' + elementName + '">' + elementName + '</div>');
} else {
jQuery('.error-' + elementName).show();
}
}
}
// Digits
if (rule == 'digits' && ruleOption == true) {
if ((/^\d+$/).test(element.val())) {
// Do nothing
} else {
elementValid = false;
}
if (!elementValid) {
fieldsValid = false;
if (jQuery('.error-' + elementName).length == 0) {
errorDiv.append('<div class="error-' + elementName + '">' + elementName + '</div>');
} else {
jQuery('.error-' + elementName).show();
}
}
}
// Multiple Emails
if (rule == 'multipleEmails' && ruleOption == true) {
var emailsArr = element.val().replace(/\s/g, '').split(/,|;/);
for (var i = 0; i < emailsArr.length; i++) {
if ((/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/).test(emailsArr[i])) {
// Do nothing
} else {
elementValid = false;
}
}
if (!elementValid) {
fieldsValid = false;
if (jQuery('.error-' + elementName).length == 0) {
errorDiv.append('<div class="error-' + elementName + '">' + elementName + '</div>');
} else {
jQuery('.error-' + elementName).show();
}
}
}
});
if (bindEvents) {
var currentOption = {};
currentOption[elementIdorName] = rules;
// Bind events to validate on the fly
switch (elementType) {
case 'text':
case 'email':
case 'number':
case 'textarea':
element.unbind('keyup.customValidation-' + elementName).bind('keyup.customValidation-' + elementName, function(e) {
return customValidation(currentOption, false);
});
break;
case 'radio':
case 'checkbox':
jQuery('input[name=' + elementIdorName + ']').each(function() {
jQuery(this).unbind('click.customValidation-' + elementName).bind('change.customValidation-' + elementName, function(e) {
console.log(e);
return customValidation(currentOption);
});
});
break;
case 'select':
case 'select-one':
case 'select-multiple':
element.unbind('change.customValidation-' + elementName).bind('change.customValidation-' + elementName, function(e) {
return customValidation(currentOption, false);
});
break;
}
}
});
return fieldsValid;
}
答案 0 :(得分:3)
是的,使用三元运算符:
<%= render f.object.manager? ? 'manager_fields' : 'staff_fields' , :f => f %>
如果您可以更改设计,我会为您提供更好的解决方案。其后如下:
使用Rails enum功能。
使用迁移在desgination
模型中将字段Employee
添加为整数字段。
然后在模型中:
enum designation: [ :staff, :manager ]
然后,您将在designation
列中存储,manager
(值为1)或staff
(值为0)。现在在视图内部调用<%= render f.object.desgination , :f => f %>
。你应该有_manager.html.erb
和_staff.html.erb
2个部分。
你完成了!
答案 1 :(得分:3)
是的,但这可能看起来有点难看:
<%= f.simple_fields for :employees do |f| %>
<%= render (f.object.manager? ? 'manager_fields' : 'staff_fields'), :f => f %>
<% end %>
我可能会创建一个帮助方法,例如在ApplicationHelper
或EmployeesHelper
文件中:
def get_employee_partial(employee)
employee.manager? ? 'manager_fields' : 'staff_fields'
end
然后以形式:
<%= render get_employee_partial(f.object), :f => f %>
答案 2 :(得分:2)
您可以通过执行以下操作来实现条件渲染:
<%= f.simple_fields for :employees do |f| %>
<% if f.object.manager? %>
<%= render 'manager_fields', :f => f %>
<% elsif f.object.staff? %>
<%= render 'staff_fields', :f => f %>
<% end %>
<% end %>
如果您只计划在Employee模型中只有manager
和staff
个角色,那么您可以使用三元运算符来简化上述操作,例如 R_O_R '答案。
您可能希望从视图模板中抽象出条件逻辑。你可以通过创建一个帮助方法来实现这一点,如 Surya 的回答所示。
希望有所帮助!
答案 3 :(得分:1)
<%= f.simple_fields for :employees do |e| %>
<% partial_name = e.object.manager? ? 'manager' : 'staff' %>
<%= render "#{partial_name}_fields" %>
<% end %>