I added two new input (ass1 and ass2) to a form, created the columns in the database, added it to $fillable in the model, and method in Vue file.
The challenge is that every other input saves to the database but my new inputs are not stored to the database.
If I input directly to the database, the data will show up for edit/update but will not store. I have checked and checked through the code and can't find any issue, no error message so far.
If you need any other details I will be happy to provide them.
Please help! I'm on a deadline.
P.S. I have very little knowledge of Vuejs, it's a bit confusing.
This is my form.vue content:
<template>
<div>
<form @submit.prevent="proceed" @keydown="assessmentForm.errors.clear($event.target.name)">
<div class="row">
<div class="col-12 col-sm-6">
<div class="form-group">
<label for="">{{trans('exam.assessment_name')}}</label>
<input class="form-control" type="text" v-model="assessmentForm.name" name="name" :placeholder="trans('exam.assessment_name')">
<show-error :form-name="assessmentForm" prop-name="name"></show-error>
</div>
</div>
<div class="col-12 col-sm-6">
<div class="form-group">
<label for="">{{trans('exam.assessment_description')}}</label>
<input class="form-control" type="text" v-model="assessmentForm.description" name="description" :placeholder="trans('exam.assessment_description')">
<show-error :form-name="assessmentForm" prop-name="description"></show-error>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<h6 class="card-title">{{trans('exam.assessment_type')}}</h6>
<template v-for="(detail,index) in assessmentForm.details">
<div class="row">
<div class="col-12 col-sm-3">
<div class="form-group">
<label for="">{{trans('exam.assessment_detail_name')}}
<button type="button" class="btn btn-xs btn-danger m-l-20" :key="`${index}_delete_detail`" v-confirm="{ok: confirmDeleteDetail(index)}" v-tooltip="trans('general.delete')"><i class="fas fa-times"></i></button></label>
<input class="form-control" type="text" v-model="detail.name" :name="getDetailName(index)" :placeholder="trans('exam.assessment_detail_name')">
<show-error :form-name="assessmentForm" :prop-name="getDetailName(index)"></show-error>
</div>
</div>
<div class="col-12 col-sm-1">
<div class="form-group">
<label for="">{{trans('exam.assessment_detail_code')}}</label>
<input class="form-control" type="text" v-model="detail.code" :name="getDetailCode(index)" :placeholder="trans('exam.assessment_detail_code')">
<show-error :form-name="assessmentForm" :prop-name="getDetailCode(index)"></show-error>
</div>
</div>
<div class="col-12 col-sm-2">
<div class="form-group">
<label for="">{{trans('exam.assessment_detail_max_mark')}}</label>
<input class="form-control" type="number" v-model="detail.max_mark" :name="getDetailMaxMarkName(index)" :placeholder="trans('exam.assessment_detail_max_mark')">
<show-error :form-name="assessmentForm" :prop-name="getDetailMaxMarkName(index)"></show-error>
</div>
</div>
<!-- <div class="col-12 col-sm-2">
<div class="form-group">
<label for="">{{trans('exam.assessment_detail_pass_percentage')}}</label>
<div class="input-group mb-3">
<input class="form-control" type="number" v-model="detail.pass_percentage" :name="getDetailPassPercentageName(index)" :placeholder="trans('exam.assessment_detail_pass_percentage')">
<div class="input-group-append">
<span class="input-group-text" id="basic-addon1">%</span>
</div>
</div>
<show-error :form-name="assessmentForm" :prop-name="getDetailPassPercentageName(index)"></show-error>
</div>
</div> -->
<div class="col-12 col-sm-2">
<div class="form-group">
<label for="">{{trans('exam.assessment_detail_ass1')}}</label>
<input class="form-control" type="number" v-model="detail.ass1" :name="getDetailAssessment1(index)" :placeholder="trans('exam.assessment_detail_ass1')">
<show-error :form-name="assessmentForm" :prop-name="getDetailAssessment1(index)"></show-error>
</div>
</div>
<div class="col-12 col-sm-2">
<div class="form-group">
<label for="">{{trans('exam.assessment_detail_ass2')}}</label>
<input class="form-control" type="number" v-model="detail.ass2" :name="getDetailAssessment2(index)" :placeholder="trans('exam.assessment_detail_ass2')">
<show-error :form-name="assessmentForm" :prop-name="getDetailAssessment2(index)"></show-error>
</div>
</div>
<div class="col-12 col-sm-4">
<div class="form-group">
<label for="">{{trans('exam.assessment_detail_description')}}</label>
<autosize-textarea v-model="detail.description" rows="2" :name="getDetailDescriptionName(index)" :placeholder="trans('resource.assessment_detail_description')"></autosize-textarea>
<show-error :form-name="assessmentForm" :prop-name="getDetailDescriptionName(index)"></show-error>
</div>
</div>
</div>
</template>
<div class="form-group">
<button type="button" @click="addRow" class="btn btn-info btn-sm waves-effect waves-light">{{trans('exam.add_new_assessment_detail')}}</button>
</div>
</div>
</div>
<div class="card-footer text-right">
<router-link to="/configuration/exam/assessment" class="btn btn-danger waves-effect waves-light ">{{trans('general.cancel')}}</router-link>
<button type="submit" class="btn btn-info waves-effect waves-light">
<span v-if="id">{{trans('general.update')}}</span>
<span v-else>{{trans('general.save')}}</span>
</button>
</div>
</form>
</div>
</template>
<script>
export default {
components: {},
data() {
return {
assessmentForm: new Form({
name: '',
description: '',
// details: ['name', 'code', 'max_mark', 'ass1', 'ass2', 'description']
details: []
})
};
},
props: ['id'],
mounted() {
if(!helper.hasPermission('access-configuration')){
helper.notAccessibleMsg();
this.$router.push('/dashboard');
}
if(this.id)
this.get();
else {
this.addRow();
}
},
methods: {
hasPermission(permission){
return helper.hasPermission(permission);
},
addRow(){
let new_index = this.assessmentForm.details.push({
name: '',
code: '',
max_mark: '',
ass1: '',
ass2: '',
// pass_percentage: '',
description: ''
})
},
confirmDeleteDetail(index){
return dialog => this.deleteDetail(index);
},
deleteDetail(index){
this.assessmentForm.details.splice(index, 1);
},
getDetailName(index){
return index+'_detail_name';
},
getDetailCode(index){
return index+'_detail_code';
},
getDetailMaxMarkName(index){
return index+'_detail_max_mark';
},
// getDetailPassPercentageName(index){
// return index+'_detail_pass_percentage';
// },
getDetailAssessment1(index){
return index+'_detail_ass1';
},
getDetailAssessment2(index){
return index+'_detail_ass2';
},
getDetailDescriptionName(index){
return index+'_detail_description';
},
proceed(){
if(this.id)
this.update();
else
this.store();
},
store(){
let loader = this.$loading.show();
this.assessmentForm.post('/api/exam/assessment')
.then(response => {
toastr.success(response.message);
this.assessmentForm.details = [];
this.addRow();
this.$emit('completed');
loader.hide();
})
.catch(error => {
loader.hide();
helper.showErrorMsg(error);
});
},
get(){
let loader = this.$loading.show();
axios.get('/api/exam/assessment/'+this.id)
.then(response => {
this.assessmentForm.name = response.name;
this.assessmentForm.description = response.description;
response.details.forEach(detail => {
this.assessmentForm.details.push({
name: detail.name,
code: detail.code,
max_mark: detail.max_mark,
ass1: detail.ass1,
ass2: detail.ass2,
description: detail.description
// pass_percentage: detail.pass_percentage,
});
});
loader.hide();
})
.catch(error => {
loader.hide();
helper.showErrorMsg(error);
this.$router.push('/configuration/exam/assessment');
});
},
update(){
let loader = this.$loading.show();
this.assessmentForm.patch('/api/exam/assessment/'+this.id)
.then(response => {
toastr.success(response.message);
loader.hide();
this.$router.push('/configuration/exam/assessment');
})
.catch(error => {
loader.hide();
helper.showErrorMsg(error);
});
}
}
}
</script>
This is the model (AssessmentDetail.php):
<?php
namespace App\Models\Configuration\Exam;
use Illuminate\Database\Eloquent\Model;
use Spatie\Activitylog\Traits\LogsActivity;
class AssessmentDetail extends Model
{
use LogsActivity;
protected $fillable = [
'exam_assessment_id',
'name',
'max_mark',
'ass1',
'ass2',
// 'pass_percentage',
'description',
'options'
];
protected $casts = ['options' => 'array'];
protected $primaryKey = 'id';
protected $table = 'exam_assessment_details';
protected static $logName = 'exam_assessment_detail';
protected static $logFillable = true;
protected static $logOnlyDirty = true;
protected static $ignoreChangedAttributes = ['updated_at'];
public function assessment()
{
return $this->belongsTo('App\Models\Configuration\Exam\Assessment', 'exam_assessment_id');
}
public function getOption(string $option)
{
return array_get($this->options, $option);
}
public function scopeFilterById($q, $id)
{
if (! $id) {
return $q;
}
return $q->where('id', '=', $id);
}
public function scopeFilterByExamAssessmentId($q, $exam_assessment_id)
{
if (! $exam_assessment_id) {
return $q;
}
return $q->where('exam_assessment_id', '=', $exam_assessment_id);
}
public function scopeFilterByName($q, $name, $s = 0)
{
if (! $name) {
return $q;
}
return $s ? $q->where('name', '=', $name) : $q->where('name', 'like', '%'.$name.'%');
}
}
This is my Controller (AssessmentController)
<?php
namespace App\Http\Controllers\Configuration\Exam;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\Configuration\Exam\AssessmentRequest;
use App\Repositories\Configuration\Exam\AssessmentRepository;
class AssessmentController extends Controller
{
protected $request;
protected $repo;
/**
* Instantiate a new controller instance.
*
* @return void
*/
public function __construct(
Request $request,
AssessmentRepository $repo
) {
$this->request = $request;
$this->repo = $repo;
$this->middleware('permission:access-configuration');
$this->middleware('academic.session.set');
}
/**
* Used to get all Exam Assessments
* @get ("/api/exam/assessment")
* @return Response
*/
public function index()
{
return $this->ok($this->repo->paginate($this->request->all()));
}
/**
* Used to print all Exam Assessments
* @post ("/api/exam/assessment/print")
* @return Response
*/
public function print()
{
$exam_assessments = $this->repo->print(request('filter'));
return view('print.configuration.exam.assessment', compact('exam_assessments'))->render();
}
/**
* Used to generate pdf all Exam Assessments
* @post ("/api/exam/assessment/pdf")
* @return Response
*/
public function pdf()
{
$exam_assessments = $this->repo->print(request('filter'));
$uuid = Str::uuid();
$pdf = \PDF::loadView('print.configuration.exam.assessment', compact('exam_assessments'))->save('../storage/app/downloads/'.$uuid.'.pdf');
return $uuid;
}
/**
* Used to store Exam Assessment
* @post ("/api/exam/assessment")
* @param ({
* @Parameter("name", type="string", required="true", description="Name of Exam Assessment"),
* @Parameter("description", type="text", required="optional", description="Description of Exam Assessment")
* })
* @return Response
*/
public function store(AssessmentRequest $request)
{
$exam_assessment = $this->repo->create($this->request->all());
// dd('$exam_assessment');
return $this->success(['message' => trans('exam.assessment_added')]);
}
/**
* Used to get Exam Assessment detail
* @get ("/api/exam/assessment/{id}")
* @param ({
* @Parameter("id", type="integer", required="true", description="Id of Exam Assessment"),
* })
* @return Response
*/
public function show($id)
{
return $this->ok($this->repo->findOrFail($id));
}
/**
* Used to update Exam Assessment
* @patch ("/api/exam/assessment/{id}")
* @param ({
* @Parameter("id", type="integer", required="true", description="Id of Exam Assessment"),
* @Parameter("name", type="string", required="true", description="Name of Exam Assessment"),
* @Parameter("description", type="text", required="optional", description="Description of Exam Assessment")
* })
* @return Response
*/
public function update($id, AssessmentRequest $request)
{
$exam_assessment = $this->repo->findOrFail($id);
$exam_assessment = $this->repo->update($exam_assessment, $this->request->all());
return $this->success(['message' => trans('exam.assessment_updated')]);
}
/**
* Used to reorder all Details of assessment
* @frontend ("/api/exam/assessment/{id}/reorder")
* @return Response
*/
public function reorder($id)
{
$exam_assessment = $this->repo->findOrFail($id);
$this->repo->reorder($exam_assessment, $this->request->all());
return $this->success(['message' => trans('exam.assessment_updated')]);
}
/**
* Used to delete Exam Assessment
* @delete ("/api/exam/assessment/{id}")
* @param ({
* @Parameter("id", type="integer", required="true", description="Id of Exam Assessment"),
* })
* @return Response
*/
public function destroy($id)
{
$exam_assessment = $this->repo->deletable($id);
$this->repo->delete($exam_assessment);
return $this->success(['message' => trans('exam.assessment_deleted')]);
}
}
These are the routes for the Assessment from Api.php
Route::get('/exam/assessment/{id}', 'Configuration\Exam\AssessmentController@show');
Route::post('/exam/assessment', 'Configuration\Exam\AssessmentController@store');
Route::patch('/exam/assessment/{id}', 'Configuration\Exam\AssessmentController@update');
Route::delete('/exam/assessment/{id}', 'Configuration\Exam\AssessmentController@destroy');
![Screenshot of Inspector, note the 80 and 1000 values were manually entered in the database.[1]](https://www.lemona.fr/i.sstatic.net/4tHR7.png)

1_detail_ass1,2_detail_ass1, etc...? Those are not defined in your$fillableproperty.