I am new to Laravel but have managed to get a contact form working and showing validation errors when there are some.
However I do have one problem and have no idea how to handle it in Laravel. When a message is sent (validation rules pass) I would like to display an alert box (Bootstrap style) saying 'Thanks, message has been sent'.
CODE
public function postContact()
{
$formData = Input::all();
// input validator with its rules
$validator = Validator::make(
array(
'name' => $formData['name'],
'email' => $formData['email'],
'subject' => $formData['subject'],
'message' => $formData['message']
),
array(
'name' => 'required|min:3',
'email' => 'required|email',
'subject' => 'required|min:6',
'message' => 'required|min:5'
)
);
if ($validator -> passes()) {
// data is valid
Mail::send('emails.message', $formData, function($message) use ($formData) {
$message -> from($formData['email'], $formData['name']);
$message -> to('info#company.com', 'John Doe') -> subject($formData['subject']);
});
return View::make('contact');
} else {
// data is invalid
return Redirect::to('/contact') -> withErrors($validator);
}
}
How can I achieve this in Laravel 4?
You could use the with method of the Redirect class:
if ($validator -> passes()) {
// data is valid
Mail::send('emails.message', $formData, function($message) use ($formData) {
$message -> from($formData['email'], $formData['name']);
$message -> to('info#company.com', 'John Doe') -> subject($formData['subject']);
});
//Redirect to contact page
return Redirect::to('/contact')->with('success', true)->with('message','That was great!');
} else {
// data is invalid
return Redirect::to('/contact') -> withErrors($validator);
}
You will be redirected to the contact page with the session variables success and message set.
Use them for an alert in your view, e.g. in a Bootstrap Alert:
with Blade
#if(Session::has('success'))
<div class="alert alert-success">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<strong>Success!</strong> {{ Session::get('message', '') }}
</div>
#endif
without Blade
<?php if(Session::has('success')): ?>
<div class="alert alert-success">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<strong>Success!</strong> <?php echo Session::get('message', ''); ?>
</div>
<?php endif; ?>
If you are using them like this you can even provide success alerts, info alerts, or any alert you want to.
When your data is INVALID you use the withErrors() method to pass some data (erros) to your route.
You can use the same process with any kind of data.
For example:
return View::make('contact')->withMessage("Thanks, message has been sent");
This method withMessage() will create a new variable message and store it in the Session for one request cycle.
So, in your view you can access it like this:
#if(Session::has('message'))
<div class="alert-box success">
{{ Session::get('message') }}
</div>
#endif
I assume you are using Bootstrap so this answer will show the message in pop up window (I test it on Laravel 5)
return View::make('contact')->with('message', "Thanks, message has been sent");
Make sure this code will be added in footer
<!-- Show Pop up Window if there is message called back -->
<?php
if(session('message'))
{
echo '<script>
document.getElementById("popup_message").click();
</script>';
}
?>
Add this function in helper.php so you can use it anywhere in your code
function message_pop_up_window($message)
{
$display = '
<a class="popup_message" id="popup_message" data-toggle="modal" data-target="#message" href="#"></a>
<div class="modal fade" id="message" role="dialog">
<div class="modal-dialog modal-md">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Messsage </h4>
</div>
<div class="modal-body">
<p>'.$message.'</p>
</div>
</div>
</div>
</div>
</div>';
return $display;
}
Then call the function in you page
{!! message_pop_up_window($message) !!}
Related
What I'm trying to acheive?
Validate the records available in the csv file that I have uploaded using maatwebsite/excel.
Set custom validation rules:
i.e.
contact_number to be integer and 13 digits
email to be strictly email etc
If all the csv file data is valid then upload in database and show
message.
If certain feild of the table is missing or not according to custom validation rules set above then show those data rows of the csv file in the blade and give user the option to update the feild and upload that data to DB.
What I'm doing?
Using Laravel Excel, I'm importing the data. I am not quite sure how the back end works.
public function import(Request $request)
{
Excel::import(new CustomersImport, $request->file);
return back()->with('success', 'User Imported Successfully.');
}
What Row Validation is showing is that they set the rules inside rules() function inside the import class and create model with table feilds. Tbh I really don't know how csv data is being transferred here. Data is also not uploading in database.
Whwn I enter dd($row) inside the model(array $row) it shows the recod of only first row of the table.
class CustomersImport implements ToModel, WithHeadingRow
{
use Importable;
public function rules(): array
{
return [
'name' => 'required|string',
'email' => 'required|string',
];
}
public function model(array $row)
{
return new Customer([
"name" => $row['name'],
"email" => $row['email'],
"contact" => $row['contact'],
"address" => $row['address'],
"nutritionplan_id" => $row['nutritionplan_id'],
"company_id" => $row['company_id'],
]);
}
}
blade file. I actuality, I want I want to show table with records that are not validated if it have errors. But for now I'm just trying to show error.
#if (count($errors) > 0)
<div class="row">
<div class="col-md-8 col-md-offset-1">
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-ban"></i> Error!</h4>
#foreach($errors->all() as $error)
{{ $error }} <br>
#endforeach
</div>
</div>
</div>
#endif
#if (Session::has('success'))
<div class="row">
<div class="col-md-8 col-md-offset-1">
<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h5>{!! Session::get('success') !!}</h5>
</div>
</div>
</div>
#endif
I'm upgrading my project from CodeIgniter 3 to CodeIgniter 4,
I'm trying to display a flashdata message inside a view but unfortunately I get differents error for each method I try.
In CodeIgniter 3, I used to call something like:
<?php if ($this->session->flashdata('message')) : ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?php echo $this->session->flashdata('message'); ?>
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<?php endif; ?>
I try the same in CodeIgniter 4 but I get this error:
ErrorException
Undefined property: CodeIgniter\View\View::$session
Can any one show me how to achieve this ?
Thanks in advance.
You can use session() function directly:
<?php if (session()->getFlashdata('message') !== NULL) : ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?php echo session()->getFlashdata('message'); ?>
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<?php endif; ?>
The context ($this) is an instance of the View class --> you don't have access to the Session instance directly
You can create new instance below
$session = \Config\Services::session();
In CodeIgniter 4 the new way to set Flash data $session->setFlashdata('item', 'value'); and to view $session->getFlashdata('item');
You can check it out here : Set Flash data in session in CodeIgniter
I just use another way to display a flashdata and it works fine.
In my controller, I added a new index to the data passed to the view:
$data['message'] = "Sorry, you must login first";
return view('login', $data);
Then in the view login.php I call it like this:
<?php if (isset($message)) : ?>
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<?php echo $message; ?>
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<?php endif; ?>
UPDATE:
I just use the markAsFlashdata() method and It works perfectly. Here's what I did in the controller just before the return method:
$_SESSION['error'] = 'Sorry, you must login first';
$session = session();
$session->markAsFlashdata('error');
Then in the view I access the flashdata using $_SESSION['error']:
<?php if (isset($_SESSION['error'])): ?>
<div class="alert alert-warning" role="alert">
<?= $_SESSION['error']; ?>
</div>
<?php endif;?>
Add this line just after echo $this->section('content');
$session = \Config\Services::session();
<?php if (isset($message)) : ?>
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<?php echo $message; ?>
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<?php endif; ?>
For now my solution has been to create a view method in BaseController.php.
The idea is to add more "common" info into the $data array.
/* In BaseController.php */
/**
* view function replaced
*/
public function view(string $name, array $data = [], array $options = []): string
{
// Inject global data
$data = array_merge($data,["controller" => $this]);
return view($name,$data,$options);
}
/**
* Temporary message
*/
public function flash($message, $type = 'info') {
$this->session->setFlashdata('flash_message',
["message" => $message, "type" => $type]);
}
public function getFlash() {
return $this->session->getFlashdata('flash_message');
}
/* In the descendant controller */
return $this->view('products/list',['products' => $products]);
/* In the view */
<div id="messages">
<?php if($flash = $controller->getFlash()) : ?>
<?= view_cell('Base::alert', $flash); ?>
<?php endif ?>
</div>
I'm trying to create a Laravel Notification. I created a table called send_profiles. When a Candidate is logged in and searching through jobs, he can send his job profile to the employer. All of that data is in a table called job_seeker_profiles. I'm developing a Job Search type of application.
I created a new Notification class called SendProfile.php:
public function toDatabase($notifiable)
{
$user = Auth::user();
return [
'user_id' => Auth::user()->id,
'employer_profile_id' => DB::table('send_profiles')->where('user_id', $user->id)->orderBy('id', 'desc')->offset(0)->limit(1)->get('employer_profile_id'),
];
}
I don't know the best way to go about this but anyway this is my route.
web.php:
Route::get('/admin/job-seeker/search/employer/{employerId}/post-a-job/{jobPostId}/send-profile', 'AdminEmployerJobPostsController#sendProfile')->name('admin.employer.post-a-job.show.send-profile')->middleware('verified');
AdminEmployerJobPostsController.php:
public function sendProfile($employerId, $jobPostId)
{
$user = Auth::user();
$jobSeekerProfile = JobSeekerProfile::all()->where('user_id', $user->id)->first();
$employerProfile = EmployerProfile::limit(1)->where('id', $employerId)->get();
$jobPosts = JobPosts::all();
$jobPost = JobPosts::findOrFail($jobPostId);
$user->sendProfile()->create();
$employerProfile->notify(new SendProfile());
return back()->with('send-profile', 'Your Profile has been sent!');
}
This is my error:
Missing required parameters for [Route: admin.employer.post-a-job.show.send-profile] [URI: admin/job-seeker/search/employer/{employerId}/post-a-job/{jobPostId}/send-profile]. (View: /Applications/XAMPP/xamppfiles/htdocs/highrjobs/resources/views/admin/employer/post-a-job/show.blade.php)
show.blade:
#extends('layouts.admin')
#section('pageTitle', 'Create a User')
#section('content')
#include('includes.job_seeker_search_employers')
<!-- The Modal -->
<div class="modal" id="myModal5">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="modal-title">{{ $jobPost->job_title }}</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<!-- Modal body -->
<div class="modal-body">
<h5>{{ $jobPost->job_description }}</h5>
</div>
<!-- Modal footer -->
<div class="modal-footer">
{!! Form::open(['method'=>'POST', 'action'=>'AdminEmployerJobPostsController#sendProfile', 'files'=>true, 'style'=>'width: 100%;']) !!}
<div class="form-group">
{!! Form::hidden('user_id', Auth::user()->id, ['class'=>'form-control']) !!}
</div>
<div class="form-group">
{!! Form::hidden('employer_profile_user_id', $employerProfile->id, ['class'=>'form-control']) !!}
</div>
<div class="row">
<div class="col">
{!! Form::button('Back', ['class'=>'btn btn-danger btn-block float-left', 'data-dismiss'=>'modal']) !!}
</div>
<div class="col">
{!! Form::submit('Send Profile', ['class'=>'btn btn-primary btn-block float-right']) !!}
{!! Form::close() !!}
</div>
</div>
<br><br><br><br>
</div>
</div>
</div>
</div>
#stop
If I remove the form, I at least don't get an error. So I actually think there is an issue with the form.
To be clear, all I want is to insert the user_id and the employer_profile_id into the send_profiles table and then send a notification to the employer.
Your route specifies a GET request to a URL that contains certain parameters:
/admin/job-seeker/search/employer/{employerId}/post-a-job/{jobPostId}/send-profile
Your form is using AdminEmployerJobPostsController#sendProfile as an action; this is translated into a URL by searching the route list, and choosing what Laravel thinks is most appropriate. Since you haven't passed anything to fill the employerId and jobPostId parameters, you're getting this error when the URL is generated.
Even if you could get the URL generated, you'd have a problem because your form is sending a POST request to this GET route.
What you need to do is ensure you have a POST route pointing to a new controller method. You won't pass any parameters to this route in the URL, so your controller method will only typically accept a Request object as a parameter. Second thing you should do is specify your form's target more accurately. Pass in the route name instead of making it guess.
public function sendProfile(Request $request)
{
// you get this here so no need to pass it in the form
$user = Auth::user();
// your relations should be set up so you don't need to do this:
// $jobSeekerProfile = JobSeekerProfile::all()->where('user_id', $user->id)->first();
// instead do this:
$jobSeekerProfile = $user->jobSeekerProfile();
// a simple find is much neater than what you had
$employerProfile = EmployerProfile::find($request->job_seeker_profile_user_id);
// not sure why this is here?
$jobPosts = JobPosts::all();
// also your form isn't passing a job post ID
$jobPost = JobPosts::findOrFail($request->jobPostId);
// ??? creating an empty something?
$user->sendProfile()->create();
$employerProfile->notify(new SendProfile());
return back()->with('send-profile', 'Your Profile has been sent!');
}
I am not able to make it work:
also it is always redirecting to `action/create' whereas i want to not to redirect to that action.
my code is like this in footer view:
<script>
jQuery(document).ready(function($) {
$("#quick-contact").on('submit',function(event) {
// $("#quick-contact").on('beforeSubmit',function(event) {
event.preventDefault(); // stopping submitting
console.log("step1");
var form = $(this);
var formData = form.serialize();
// var data = $(this).serializeArray();
var url = $(this).attr('/quick-contact/create');
$.ajax({
url: form.attr("action"),
type: form.attr("method"),
dataType: 'json',
data: formData
})
.done(function(response) {
if (response.data.success == true) {
alert("Wow you commented");
}
})
.fail(function() {
console.log("error");
});
// return false;
});
});
</script>
<?php //pjax::begin(['enablePushState' => false]); ?>
<div id="contact-form">
<?php $form = ActiveForm::begin(['action'=>'/quick-contact/create','id'=>'quick-contact','method'=>'post']); ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'email')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'message')->textarea(['rows' => 2]) ?>
<div class="form-group">
<?= Html::submitButton(Yii::t('app', 'Save'), ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
<div id="quick-contact-form">
<?php if (Yii::$app->session->hasFlash('success')): ?>
<div class="alert alert-success alert-dismissable">
<button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
<h4><i class="icon fa fa-check"></i>Saved!</h4>
<?= Yii::$app->session->getFlash('success') ?>
</div>
<?php endif; ?>
// display error message
<?php if (Yii::$app->session->hasFlash('error')): ?>
<div class="alert alert-danger alert-dismissable">
<button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
<h4><i class="icon fa fa-check"></i>Saved!</h4>
<?= Yii::$app->session->getFlash('error') ?>
</div>
<?php endif; ?>
</div></div>
<?php // pjax::end(); ?>
and in controller action like:
public function actionCreate()
{
$model = new QuickContact();
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
var_dump($_POST);
if ($model->load(Yii::$app->requset->post()) && $model->save()) {
Yii::$app->session->setFlash('success','Thanks We will get in touch with you');
// $st = Yii::$app->getTable;
// $email_template = $st->email_template(1);
Yii::$app->mailer->compose()
->setTo('info#mywebsolutions.co.in')
->setFrom(['info#mywebsolutions.co.in'])
->setSubject('QuickContact')
->setHtmlBody('Request from - '.$model->name.'<br>'.'Email - '.$model->email. '<br>'.'Message - '.$model->message)
->send();
/* Yii::$app->mailer->compose('template', ['id' => 1, 'email_template' => $email_template, 'sender_name'=>$model->name,'message'=>$model->address])
->setTo($this->email)
->setFrom([$email => "vedic"])
->setSubject($this->subject)
//->setHtmlBody('Hi '.$this->name.'<br>'.'Welcome to Nexgen'.'<br>'.'We confirm of having received your Enquiry/feedback as below'.'<br>'.$this->body )
->send();
*/
}else{
Yii::$app->session->setFlash('error','There was an error in submission.');
}
//return $this->render('/site/index');
}
// return $this->renderPartial('/site/index');
}
updated jquery script code:
Now ajax request is going through, but the response I am getting is like:
name Unknown Property
message Getting unknown property: yii\web\Application::requset
code 0
type yii\base\UnknownPropertyException
file /var/www/clients/client2/web238/web/vendor/yiisoft/yii2/base/Component.php
just replace the
$("#quick-contact").submit(function(event) {
with
$("#quick-contact").on('beforeSubmit',function(event) {
Update
The reason you are getting the error is because you have several errors in your console regarding the 3rd party scripts, and until unless you remove them you wont be able to get it working, you need to fix the following
Another thing that is missing is the return false; statement in your beforeSubmit event you should add this line after the ajax call, to prevent form submission.
$("#quick-contact").on('beforeSubmit',function(event) {
//....your code for ajax call
return false;
});
Update 2
The reason for the error is the spelling for the requset which should be rather request you need to change the line
if ($model->load(Yii::$app->requset->post()) && $model->save()) {
to
if ($model->load(Yii::$app->request->post()) && $model->save()) {
if you still into problems please add a separate question as this question addresses the ajax part only which is solved already.
I have a form. When user submits the form and gets error, I show it like this:
Register Controller
return View::make('theme-admin.user_add')->with('error_msg', validation->errors->first());
register.blade.php
#if($error_msg !== null)
<div class="alert red hideit max">
<div class="left">
<span class="red-icon"></span>
<span class="alert-text">{{ $error_msg }}</span> <-- Error message is visible here.
</div>
<div class="right">
<a class="close-red"></a>
</div>
</div>
#endif
//
Actual HTML Form
//
However, I want to move that error div into a blade file. (error.blade.php) and I want to call it with parameters when there is an error.
It will look like this.
NEW register.blade.php
{{ MESSAGE_CONTENT }} //This should be replaced with error.blade.php dynamically
//
Actual HTML Form
//
MESSAGE_CONTENT will be included via error.blade.php
error.blade.php
<div class="alert red hideit max">
<div class="left">
<span class="red-icon"></span>
<span class="alert-text">{{ $message }}</span> <-- Error message is visible here.
</div>
<div class="right">
<a class="close-red"></a>
</div>
</div>
Let's say form failed and I got some errors. I will load error.blade.php so messages will get RED background etc.
Something like this;
return View::make('theme-admin.user_add')->with(message_content', (Load error.blade.php here))->with('message', $validation->errors->first();
If the form succeeds, I'll just load success.blade.php in messages area and messages will look with GREEN background.
return View::make('theme-admin.user_add')->with(message_content', (Load success.blade.php here))->with('message', 'You successfully registered');
You probably got the logic.
How can I do this?
Ps. Image example: http://i.imgur.com/QExAiuA.png
A clean solution may be to have a simple alert object with a type and msg.
//in controller
$alert->type = 'error'; // or 'success'
$alert->class = 'red'; // or 'green'
$alert->msg = $validation->errors->first(); // or 'You successfully registered'
return View::make('theme-admin.user_add')->with('alert', $alert);
//register.blade.php
#include('alert')
//Actual HTML Form
//alert.blade.php
#if(isset($alert))
<div class="alert {{$alert->class}} hideit max">
<div class="left">
<span class="red-icon"></span>
<span class="alert-text">{{ $alert->msg }}</span>
</div>
<div class="right">
<a class="close-{{$alert->class}}"></a>
</div>
</div>
#endif
You should create your view (View::make()) in a route defined for GET, and then handle your form input in your POST route:
//routes.php
Route::get('admin/adduser', array('as' => 'adduser', 'do' => function()
{
return View::make('theme-admin.user_add');
}));
//route for handling form input
Route::post('register', array('before' => 'csrf', function()
{
$rules = array(
//your vailidation rules here..
);
$validation = Validator::make(Input::all(), $rules);
if ($validation->fails())
{
//re-populate form if invalid values, so add flashing input by with_input()
//also pass errors by using with_errors
return Redirect::to('adduser')->with_input()->with_errors($validation);
}
else {
//use the named route we defined in Route:get above
return Redirect:to('adduser')->with('message', 'Successfully added the new user!');
}
}));
There is no need to create new views for dislaying error and success messages. If you want to seperate your success and error into their own blade templates then you could use the following in your adduser.blade.php:
//adduser.blade.php
#if($errors->has())
#include('errormsg'); //use {{ $errors->first() }} or #foreach($errors->all() as $message) to print error message(s)
#else
#include('success'); //use {{ $message }} to print success
#endif
However you can also use sections in your view, and instead put both the success and error message inside the same view:
//feedback.blade.php
#section('error')
<em class="error">{{ $errors->first() }}</em>
#endsection
#section('success')
<em class="success">{{ $message }}</em>
#endsection
//adduser.blade.php
#include('feedback');
#if($errors->has())
#yield('error');
#else
#yield('success');
#endif
Hope that helps.
I found the solution myself. I needed Nested Views feature.
$view = View::make('home');
$view->nest('content', 'orders', array('orders' => $orders));
Refer to Laravel documentation for more information.