优化表单前端验证
This commit is contained in:
parent
5b503d9038
commit
2655bb8895
|
|
@ -11,6 +11,9 @@ trim_trailing_whitespace = true
|
|||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{js,scss}]
|
||||
indent_size = 2
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,15 @@ class InputLocale extends Component
|
|||
public string $title;
|
||||
public string $width;
|
||||
public $value;
|
||||
public bool $required;
|
||||
|
||||
public function __construct(string $name, string $title, $value, ?string $width = '400')
|
||||
public function __construct(string $name, string $title, $value, ?string $width = '400', ?bool $required = false)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->title = $title;
|
||||
$this->value = $value;
|
||||
$this->width = $width;
|
||||
$this->value = $value;
|
||||
$this->required = $required;
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
|
|
|||
|
|
@ -17012,3 +17012,8 @@ textarea.form-control-lg {
|
|||
.btn-link:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.was-validated .form-control:valid, .form-control.is-valid {
|
||||
border-color: #e2e2e2;
|
||||
background-image: none;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2066,6 +2066,8 @@ __webpack_require__.r(__webpack_exports__);
|
|||
/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./common */ "./resources/beike/admin/js/common.js");
|
||||
/* harmony import */ var _autocomplete__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./autocomplete */ "./resources/beike/admin/js/autocomplete.js");
|
||||
/* harmony import */ var _autocomplete__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_autocomplete__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var _bootstrap_validation__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./bootstrap-validation */ "./resources/beike/admin/js/bootstrap-validation.js");
|
||||
/* harmony import */ var _bootstrap_validation__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_bootstrap_validation__WEBPACK_IMPORTED_MODULE_3__);
|
||||
var _document$querySelect;
|
||||
|
||||
|
||||
|
|
@ -2073,6 +2075,7 @@ window.$http = _js_http__WEBPACK_IMPORTED_MODULE_0__["default"];
|
|||
|
||||
window.bk = _common__WEBPACK_IMPORTED_MODULE_1__["default"];
|
||||
|
||||
|
||||
var base = document.querySelector('base').href;
|
||||
var asset = document.querySelector('meta[name="asset"]').content;
|
||||
var editor_language = ((_document$querySelect = document.querySelector('meta[name="editor_language"]')) === null || _document$querySelect === void 0 ? void 0 : _document$querySelect.content) || 'zh_cn';
|
||||
|
|
@ -2297,6 +2300,30 @@ $(function () {
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./resources/beike/admin/js/bootstrap-validation.js":
|
||||
/*!**********************************************************!*\
|
||||
!*** ./resources/beike/admin/js/bootstrap-validation.js ***!
|
||||
\**********************************************************/
|
||||
/***/ (() => {
|
||||
|
||||
// Example starter JavaScript for disabling form submissions if there are invalid fields
|
||||
$(function () {
|
||||
var forms = document.querySelectorAll(".needs-validation"); // Loop over them and prevent submission
|
||||
|
||||
Array.prototype.slice.call(forms).forEach(function (form) {
|
||||
form.addEventListener("submit", function (event) {
|
||||
if (!form.checkValidity()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
form.classList.add("was-validated");
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./resources/beike/admin/js/common.js":
|
||||
/*!********************************************!*\
|
||||
!*** ./resources/beike/admin/js/common.js ***!
|
||||
|
|
|
|||
|
|
@ -17042,3 +17042,8 @@ textarea.form-control-lg {
|
|||
.breadcrumb a {
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
.was-validated .form-control:valid, .form-control.is-valid {
|
||||
border-color: #ced4da;
|
||||
background-image: none;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2052,6 +2052,30 @@ module.exports = {
|
|||
};
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./resources/beike/shop/default/js/bootstrap-validation.js":
|
||||
/*!*****************************************************************!*\
|
||||
!*** ./resources/beike/shop/default/js/bootstrap-validation.js ***!
|
||||
\*****************************************************************/
|
||||
/***/ (() => {
|
||||
|
||||
// Example starter JavaScript for disabling form submissions if there are invalid fields
|
||||
$(function () {
|
||||
var forms = document.querySelectorAll(".needs-validation"); // Loop over them and prevent submission
|
||||
|
||||
Array.prototype.slice.call(forms).forEach(function (form) {
|
||||
form.addEventListener("submit", function (event) {
|
||||
if (!form.checkValidity()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
form.classList.add("was-validated");
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./resources/beike/shop/default/js/common.js":
|
||||
|
|
@ -2683,6 +2707,8 @@ __webpack_require__.r(__webpack_exports__);
|
|||
/* harmony import */ var _product__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_product__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var _header__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./header */ "./resources/beike/shop/default/js/header.js");
|
||||
/* harmony import */ var _header__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_header__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _bootstrap_validation__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./bootstrap-validation */ "./resources/beike/shop/default/js/bootstrap-validation.js");
|
||||
/* harmony import */ var _bootstrap_validation__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_bootstrap_validation__WEBPACK_IMPORTED_MODULE_4__);
|
||||
|
||||
|
||||
window.bk = _common__WEBPACK_IMPORTED_MODULE_1__["default"];
|
||||
|
|
@ -2691,6 +2717,7 @@ var token = document.querySelector('meta[name="csrf-token"]').content;
|
|||
var base = document.querySelector('base').href;
|
||||
|
||||
|
||||
|
||||
$(document).ready(function ($) {
|
||||
$(document).on('click', '.offcanvas-products-delete', function () {
|
||||
var _this = this;
|
||||
|
|
|
|||
|
|
@ -69,4 +69,9 @@ $alert-padding-y: 0.5rem;
|
|||
&:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.was-validated .form-control:valid, .form-control.is-valid {
|
||||
border-color: $input-border-color;
|
||||
background-image: none;
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ window.$http = http;
|
|||
import common from "./common";
|
||||
window.bk = common;
|
||||
import "./autocomplete";
|
||||
import "./bootstrap-validation";
|
||||
|
||||
const base = document.querySelector('base').href;
|
||||
const asset = document.querySelector('meta[name="asset"]').content;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
// Example starter JavaScript for disabling form submissions if there are invalid fields
|
||||
$(function () {
|
||||
var forms = document.querySelectorAll(".needs-validation");
|
||||
|
||||
// Loop over them and prevent submission
|
||||
Array.prototype.slice.call(forms).forEach(function (form) {
|
||||
form.addEventListener(
|
||||
"submit",
|
||||
function (event) {
|
||||
if (!form.checkValidity()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
form.classList.add("was-validated");
|
||||
},
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -2,7 +2,10 @@
|
|||
@foreach (locales() as $index => $locale)
|
||||
<div class="d-flex wp-{{ $width }}">
|
||||
<span class="input-group-text wp-100 px-1" id="basic-addon1">{{ $locale['name'] }}</span>
|
||||
<input type="text" name="{{ $formatName($locale['code']) }}" value="{{ $formatValue($locale['code']) }}" class="form-control short" placeholder="{{ $locale['name'] }}">
|
||||
<input type="text" name="{{ $formatName($locale['code']) }}" value="{{ $formatValue($locale['code']) }}"
|
||||
class="form-control short" placeholder="{{ $locale['name'] }}" @if ($required) required @endif>
|
||||
<span class="invalid-feedback w-auto"
|
||||
style="white-space:nowrap;">{{ __('common.error_required', ['name' => $title]) }}</span>
|
||||
</div>
|
||||
@if ($attributes->has('required'))
|
||||
@error($errorKey($locale['code']))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
<x-admin::form.row :title="$title" :required="$required">
|
||||
<input type="text" name="{{ $name }}" class="form-control wp-{{ $width }} {{ $error ? 'is-invalid' : '' }}" value="{{ $value }}" placeholder="{{ $title }}">
|
||||
@if ($error)
|
||||
<span class="invalid-feedback" role="alert">{{ $error }}</span>
|
||||
@endif
|
||||
<input type="text" name="{{ $name }}"
|
||||
class="form-control wp-{{ $width }} {{ $error ? 'is-invalid' : '' }}" value="{{ $value }}"
|
||||
placeholder="{{ $title }}" @if ($required) required @endif>
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@if ($error)
|
||||
{{ $error }}
|
||||
@else
|
||||
{{ __('common.error_required', ['name' => $title]) }}
|
||||
@endif
|
||||
</span>
|
||||
{{ $slot }}
|
||||
</x-admin::form.row>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
@section('content')
|
||||
<div id="plugins-app-form" class="card h-min-600">
|
||||
<div class="card-body">
|
||||
<form action="{{ $page->id ? admin_route('pages.update', [$page->id]) : admin_route('pages.store') }}" method="POST">
|
||||
<form novalidate class="needs-validation" action="{{ $page->id ? admin_route('pages.update', [$page->id]) : admin_route('pages.store') }}" method="POST">
|
||||
@csrf
|
||||
@method($page->id ? 'PUT' : 'POST')
|
||||
|
||||
|
|
@ -30,12 +30,13 @@
|
|||
error="{{ $error_title }}"
|
||||
name="descriptions[{{ $language['code'] }}][title]"
|
||||
title="信息标题"
|
||||
:required="true"
|
||||
value="{{ old('title', $descriptions[$language['code']]['title'] ?? '') }}"
|
||||
/>
|
||||
|
||||
<x-admin::form.row title="内容">
|
||||
<div class="w-max-1000">
|
||||
<textarea name="descriptions[{{ $language['code'] }}][content]" data-tinymce-height="600" class="form-control tinymce">
|
||||
<textarea required name="descriptions[{{ $language['code'] }}][content]" data-tinymce-height="600" class="form-control tinymce">
|
||||
{{ old('content', $descriptions[$language['code']]['content'] ?? '') }}
|
||||
</textarea>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
@if (session('success'))
|
||||
<x-admin-alert type="success" msg="{{ session('success') }}" class="mt-4"/>
|
||||
@endif
|
||||
<form action="{{ admin_route('plugins.update', [$plugin->code]) }}" method="POST">
|
||||
<form class="needs-validation" novalidate action="{{ admin_route('plugins.update', [$plugin->code]) }}" method="POST">
|
||||
@csrf
|
||||
{{ method_field('put') }}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
<div class="card">
|
||||
{{-- <div class="card-header"><h6 class="card-title">基础信息</h6></div> --}}
|
||||
<div class="card-body">
|
||||
<form action="{{ $product->id ? admin_route('products.update', $product) : admin_route('products.store') }}"
|
||||
<form novalidate class="needs-validation" action="{{ $product->id ? admin_route('products.update', $product) : admin_route('products.store') }}"
|
||||
method="POST" id="app">
|
||||
@csrf
|
||||
@method($product->id ? 'PUT' : 'POST')
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active" id="tab-basic">
|
||||
<h6 class="border-bottom pb-3 mb-4">数据</h6>
|
||||
<x-admin-form-input-locale :width="600" name="descriptions.*.name" title="名称" :value="$descriptions" required />
|
||||
<x-admin-form-input-locale :width="600" name="descriptions.*.name" title="名称" :value="$descriptions" :required="true" />
|
||||
<x-admin::form.row title="图片">
|
||||
<draggable
|
||||
element="div"
|
||||
|
|
|
|||
|
|
@ -132,4 +132,9 @@ $alert-padding-y: 0.5rem;
|
|||
a {
|
||||
color: #212529;
|
||||
}
|
||||
}
|
||||
|
||||
.was-validated .form-control:valid, .form-control.is-valid {
|
||||
border-color: $input-border-color;
|
||||
background-image: none;
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ const base = document.querySelector('base').href;
|
|||
|
||||
import './product';
|
||||
import './header'
|
||||
import './bootstrap-validation'
|
||||
|
||||
$(document).ready(function ($) {
|
||||
$(document).on('click', '.offcanvas-products-delete', function () {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
// Example starter JavaScript for disabling form submissions if there are invalid fields
|
||||
$(function () {
|
||||
var forms = document.querySelectorAll(".needs-validation");
|
||||
|
||||
// Loop over them and prevent submission
|
||||
Array.prototype.slice.call(forms).forEach(function (form) {
|
||||
form.addEventListener(
|
||||
"submit",
|
||||
function (event) {
|
||||
if (!form.checkValidity()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
form.classList.add("was-validated");
|
||||
},
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -18,5 +18,5 @@ return [
|
|||
'updated_success' => 'Updated Successfully!',
|
||||
'created_success' => 'Created Successfully!',
|
||||
'get_success' => 'Get Successfully!',
|
||||
|
||||
'error_required' => 'Please fill out the :name',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* currency.php
|
||||
*
|
||||
* @copyright 2022 opencart.cn - All Rights Reserved
|
||||
* @link http://www.guangdawangluo.com
|
||||
* @author TL <mengwb@opencart.cn>
|
||||
* @created 2022-07-28 17:21:38
|
||||
* @modified 2022-07-28 17:21:38
|
||||
*/
|
||||
return [
|
||||
'error_required' => '请填写 :name',
|
||||
];
|
||||
|
||||
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
</nav>
|
||||
|
||||
<div class="row">
|
||||
<x-shop-sidebar/>
|
||||
<x-shop-sidebar />
|
||||
|
||||
<div class="col-12 col-md-9">
|
||||
<div class="card h-min-600">
|
||||
|
|
@ -26,17 +26,18 @@
|
|||
<h5 class="card-title">修改个人信息</h5>
|
||||
</div>
|
||||
<div class="card-body h-600">
|
||||
<form action="{{ shop_route('account.edit.update') }}" method="POST">
|
||||
<form novalidate class="needs-validation" action="{{ shop_route('account.edit.update') }}" method="POST">
|
||||
@csrf
|
||||
{{ method_field('put') }}
|
||||
|
||||
@if (session('success'))
|
||||
<x-shop-alert type="success" msg="{{ session('success') }}" class="mt-4"/>
|
||||
<x-shop-alert type="success" msg="{{ session('success') }}" class="mt-4" />
|
||||
@endif
|
||||
|
||||
<div class="bg-light rounded-3 p-4 mb-4" style="background: #f6f9fc;">
|
||||
<div class="d-flex align-items-center">
|
||||
<img class="rounded-3" id="avatar" src="{{ image_resize($customer->avatar, 200, 200) }}" width="90">
|
||||
<img class="rounded-3" id="avatar" src="{{ image_resize($customer->avatar, 200, 200) }}"
|
||||
width="90">
|
||||
<div class="ps-3">
|
||||
<label class="btn btn-light shadow-sm bg-body mb-2" data-toggle="tooltip" title="Change your avatar">
|
||||
<i class="bi bi-arrow-repeat"></i> 修改头像
|
||||
|
|
@ -50,17 +51,19 @@
|
|||
<div class="row gx-4 gy-3">
|
||||
<div class="col-sm-6">
|
||||
<label class="form-label">名称</label>
|
||||
<input class="form-control {{ $errors->has('name') ? 'is-invalid' : '' }}" type="text" name="name" value="{{ old('name', $customer->name ?? '') }}">
|
||||
@if ($errors->has('name'))
|
||||
<span class="invalid-feedback" role="alert">{{ $errors->first('name') }}</span>
|
||||
@endif
|
||||
<input class="form-control {{ $errors->has('name') ? 'is-invalid' : '' }}" type="text" name="name"
|
||||
value="{{ old('name', $customer->name ?? '') }}" required>
|
||||
<span class="invalid-feedback"
|
||||
role="alert">{{ $errors->has('name') ? $errors->first('name') : __('common.error_required', ['name' => '名称']) }}</span>
|
||||
{{-- @if ($errors->has('name'))@endif --}}
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="form-label">邮箱</label>
|
||||
<input class="form-control {{ $errors->has('email') ? 'is-invalid' : '' }}" type="email" name="email" value="{{ old('name', $customer->email ?? '') }}">
|
||||
@if ($errors->has('email'))
|
||||
<span class="invalid-feedback" role="alert">{{ $errors->first('email') }}</span>
|
||||
@endif
|
||||
<input class="form-control {{ $errors->has('email') ? 'is-invalid' : '' }}" type="email"
|
||||
name="email" value="{{ old('name', $customer->email ?? '') }}" required>
|
||||
<span class="invalid-feedback"
|
||||
role="alert">{{ $errors->has('email') ? $errors->first('email') : __('common.error_required', ['name' => '邮箱']) }}</span>
|
||||
{{-- @if ($errors->has('email'))@endif --}}
|
||||
</div>
|
||||
<div class="col-12 mt-4">
|
||||
<button class="btn btn-primary mt-sm-0" type="submit">提交</button>
|
||||
|
|
@ -73,26 +76,27 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="modal" tabindex="-1" data-bs-backdrop="static" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">裁剪</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="img-container">
|
||||
<img id="cropper-image" src="{{ image_resize('/') }}" class="img-fluid">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary cropper-crop">确定</button>
|
||||
<div class="modal fade" id="modal" tabindex="-1" data-bs-backdrop="static" aria-labelledby="exampleModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">裁剪</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="img-container">
|
||||
<img id="cropper-image" src="{{ image_resize('/') }}" class="img-fluid">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary cropper-crop">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('add-scripts')
|
||||
|
|
@ -104,7 +108,7 @@
|
|||
|
||||
$('#update-btn').change(function(e) {
|
||||
var files = e.target.files;
|
||||
var done = function (url) {
|
||||
var done = function(url) {
|
||||
$(this).val('');
|
||||
image.src = url;
|
||||
$('#modal').modal('show');
|
||||
|
|
@ -121,7 +125,7 @@
|
|||
done(URL.createObjectURL(file));
|
||||
} else if (FileReader) {
|
||||
reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
reader.onload = function(e) {
|
||||
done(reader.result);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
|
|
@ -129,12 +133,12 @@
|
|||
}
|
||||
});
|
||||
|
||||
$modal.on('shown.bs.modal', function () {
|
||||
$modal.on('shown.bs.modal', function() {
|
||||
cropper = new Cropper(image, {
|
||||
aspectRatio: 1,
|
||||
viewMode: 3,
|
||||
});
|
||||
}).on('hidden.bs.modal', function () {
|
||||
}).on('hidden.bs.modal', function() {
|
||||
cropper.destroy();
|
||||
cropper = null;
|
||||
});
|
||||
|
|
@ -152,7 +156,7 @@
|
|||
});
|
||||
initialAvatarURL = avatar.src;
|
||||
// avatar.src = canvas.toDataURL();
|
||||
canvas.toBlob(function (blob) {
|
||||
canvas.toBlob(function(blob) {
|
||||
var formData = new FormData();
|
||||
|
||||
formData.append('file', blob, 'avatar.png');
|
||||
|
|
|
|||
Loading…
Reference in New Issue