display custom errors and implement in sample

This commit is contained in:
manuel 2022-08-20 22:51:15 +02:00
parent 1c450a7291
commit 16e8c36f9f
8 changed files with 46 additions and 12 deletions

View File

@ -78,9 +78,12 @@ pub fn derive_actix_admin_view_model(input: proc_macro::TokenStream) -> proc_mac
fn validate_entity(model: &mut ActixAdminModel) { fn validate_entity(model: &mut ActixAdminModel) {
Entity::validate_model(model); Entity::validate_model(model);
let custom_errors = Entity::validate(&model); if !model.has_errors() {
let active_model = ActiveModel::from(model.clone());
let custom_errors = Entity::validate(&active_model);
model.custom_errors = custom_errors; model.custom_errors = custom_errors;
} }
}
async fn create_entity(db: &DatabaseConnection, mut model: ActixAdminModel) -> ActixAdminModel { async fn create_entity(db: &DatabaseConnection, mut model: ActixAdminModel) -> ActixAdminModel {
let new_model = ActiveModel::from(model.clone()); let new_model = ActiveModel::from(model.clone());

View File

@ -39,3 +39,13 @@ impl Related<super::post::Entity> for Entity {
} }
impl ActiveModelBehavior for ActiveModel {} impl ActiveModelBehavior for ActiveModel {}
impl ActixAdminModelValidationTrait<ActiveModel> for Entity {
fn validate(model: &ActiveModel) -> HashMap<String, String> {
let mut errors = HashMap::new();
if model.my_decimal.clone().unwrap() < Decimal::from(100 as i16) {
errors.insert("my_decimal".to_string(), "Must be larger than 100".to_string());
}
errors
}
}

View File

@ -75,3 +75,5 @@ impl Display for Tea {
} }
} }
} }
impl ActixAdminModelValidationTrait<ActiveModel> for Entity {}

View File

@ -13,7 +13,7 @@ pub mod builder;
pub mod prelude { pub mod prelude {
pub use crate::builder::{ ActixAdminBuilder, ActixAdminBuilderTrait}; pub use crate::builder::{ ActixAdminBuilder, ActixAdminBuilderTrait};
pub use crate::model::{ ActixAdminModel, ActixAdminModelTrait}; pub use crate::model::{ ActixAdminModel, ActixAdminModelValidationTrait, ActixAdminModelTrait};
pub use crate::view_model::{ ActixAdminViewModel, ActixAdminViewModelTrait, ActixAdminViewModelField, ActixAdminViewModelSerializable, ActixAdminViewModelFieldType }; pub use crate::view_model::{ ActixAdminViewModel, ActixAdminViewModelTrait, ActixAdminViewModelField, ActixAdminViewModelSerializable, ActixAdminViewModelFieldType };
pub use actix_admin_macros::{ DeriveActixAdmin, DeriveActixAdminModel, DeriveActixAdminViewModel, DeriveActixAdminEnumSelectList, DeriveActixAdminModelSelectList }; pub use actix_admin_macros::{ DeriveActixAdmin, DeriveActixAdminModel, DeriveActixAdminViewModel, DeriveActixAdminEnumSelectList, DeriveActixAdminModelSelectList };
pub use crate::{ ActixAdminAppDataTrait, ActixAdmin, ActixAdminConfiguration }; pub use crate::{ ActixAdminAppDataTrait, ActixAdmin, ActixAdminConfiguration };

View File

@ -17,8 +17,10 @@ pub trait ActixAdminModelTrait {
) -> (usize, Vec<ActixAdminModel>); ) -> (usize, Vec<ActixAdminModel>);
fn get_fields() -> Vec<ActixAdminViewModelField>; fn get_fields() -> Vec<ActixAdminViewModelField>;
fn validate_model(model: &mut ActixAdminModel); fn validate_model(model: &mut ActixAdminModel);
// function to be overridable for custom error handling }
fn validate(_model: &ActixAdminModel) -> HashMap<String, String> {
pub trait ActixAdminModelValidationTrait<T> {
fn validate(_model: &T) -> HashMap<String, String> {
return HashMap::new(); return HashMap::new();
} }
} }

View File

@ -5,7 +5,7 @@
{% for model_field in view_model.fields -%} {% for model_field in view_model.fields -%}
<div class="field"> <div class="field">
<label class="{{ model_field | get_html_input_type }}" for="{{ model_field.field_name }}"> <label class="{{ model_field | get_html_input_type }}" for="{{ model_field.field_name }}">
{{ model_field.field_name | split(pat="_") | join(sep=" ") | title }} {{ model_field.field_name | split(pat="_") | join(sep=" ") | title }}{% if not model_field.is_option %} *{% endif %}
</label> </label>
<div class="control"> <div class="control">
{% if model_field.field_type == "SelectList" %} {% if model_field.field_type == "SelectList" %}
@ -16,6 +16,12 @@
{% include "form_elements/input.html" %} {% include "form_elements/input.html" %}
{% endif %} {% endif %}
</div> </div>
{% if model.errors | get(key=model_field.field_name, default="" ) !="" %}
<p class="help is-danger">{{ model.errors | get(key=model_field.field_name) }}</p>
{% endif %}
{% if model.custom_errors | get(key=model_field.field_name, default="" ) !="" %}
<p class="help is-danger">{{ model.custom_errors | get(key=model_field.field_name) }}</p>
{% endif %}
</div> </div>
{%- endfor %} {%- endfor %}
<div class="field is-grouped"> <div class="field is-grouped">

View File

@ -1,7 +1,12 @@
<input <input
class="{{ model_field | get_html_input_class }} {% if model.errors | get(key=model_field.field_name,default="" ) !="" %}is-danger{% endif %}" class="{{ model_field | get_html_input_class }}
{% if
model.errors | get(key=model_field.field_name, default="" ) !=""
or
model.custom_errors | get(key=model_field.field_name, default="" ) !=""
%}is-danger{% endif %}"
type="{{ model_field | get_html_input_type }}" type="{{ model_field | get_html_input_type }}"
value="{{ model.values | get(key=model_field.field_name, default="") | split(pat=" _") | join(sep=" " ) | title }}" value="{{ model.values | get(key=model_field.field_name, default="") }}"
name="{{ model_field.field_name }}" name="{{ model_field.field_name }}"
placeholder="{{ model_field.field_name }}" placeholder="{{ model_field.field_name }}"
aria-label="{{ model_field.field_name }}" aria-label="{{ model_field.field_name }}"

View File

@ -1,4 +1,10 @@
<div class="select {% if model.errors | get(key=model_field.field_name, default="" ) !="" %}is-danger{% endif %}"> <div class="select
{% if
model.errors | get(key=model_field.field_name, default="" ) !=""
or
model.custom_errors | get(key=model_field.field_name, default="" ) !=""
%}is-danger{% endif %}"
>
<select name="{{ model_field.field_name }}"> <select name="{{ model_field.field_name }}">
{% if model_field.is_option %} {% if model_field.is_option %}
<option value=""></option> <option value=""></option>