Need help with refactoring my own horrible code Hi! I've been learning laravel for quite sometime now (but I'm no where near an expert yet). My project is a form builder. This means that I have different types of questions, IE: radio, checkbox and a few custom question types. I can't for the life of me figure out how to get a round the if(question->type == 'questiontype') situation.
The result is this code which gets increasingly hard to work with (you dont need to read it all, the problem is painfully obvious I think):
@section ('content')
<div class="card">
<div class="card-content">
<div id="survey">
{!! Form::open(['action'=>['AnswerController@store', $survey->id], 'id' => 'surveyForm']) !!}
<div class="row">
<?php $inc = 0;?>
@foreach ($section_array as $key => $section)
<div id="sales-<?= $inc;?>" class="col s12 tabcontent">
@foreach ($section as $question)
@if ($question->question_type != 'kleurvraag' AND $question->question_type != 'sectionend')
<div class="survey-question">
@endif
@if ($question->question_type != 'html' AND $question->question_type != 'sectionend' AND $question->question_type != 'kleurvraag')
<p class="flow-text">{!! $question->title !!}</p>
@endif
@if ($question->question_type != 'sectionend' AND $question->question_type != 'kleurvraag')
@if ($question->subtitle)<p class="subtitle">{{$question->subtitle}}</p>@endif
@endif
@if ($question->question_type === 'html')
{!! ($question->option_name[0]) !!}
@elseif ($question->question_type === 'slider')
<p class="range-field">
<input type="range" name="{{ $question->id }}" id="{{ $question->id }}" min="{{$question->option_name[0]}}" max="{{$question->option_name[1]}}"/>
</p>
@elseif ($question->question_type === 'text')
<input type="text" name="{{ $question->id}}" id="answer{{ $question->id }}" placeholder="{{$question->option_name[0]}}">
@elseif ($question->question_type === 'textarea')
<div class="input-field col s12">
<textarea name="{{ $question->id }}" id="textarea1{{ $question->id }}" class="materialize-textarea" placeholder="{{$question->option_name[0]}}" ></textarea>
</div>
@elseif ($question->question_type === 'radio' && ! empty($question->option_name))
<div class="rb-wrapper">
@foreach ($question->option_name as $key=>$value)
<p class="rb">
<input type="radio" name="{{ $question->id }}" id="{{$question->id}}-{{ $key }}" value="{{ $value }}" />
<label for="{{$question->id}}-{{ $key }}">{{ $value }}</label>
</p>
@endforeach
</div>
@elseif ($question->question_type === 'checkbox' && ! empty($question->option_name))
<div class="cb-wrapper">
@foreach ($question->option_name as $key=>$value)
<p class="cb">
<input type="checkbox" name="{{ $question->id }}[]" id="{{$question->id}}-{{ $key }}" value="{{ $value }}" />
<label for="{{$question->id}}-{{ $key }}">{{ $value }}</label>
</p>
@endforeach
</div>
@elseif ($question->question_type === 'datepicker')
<input type="date" name="{{ $question->id }}" id="{{ $question->id }}-{{ $key }}" class="datepicker" placeholder="{{$question->option_name[0]}}" />
@elseif ($question->question_type === 'kleurvraag')
<p class="color-q">
<input type="radio" name="{{ $question->id }}" id="{{ $question->id }}-1" class="color-left" value="1" />
<label for="{{ $question->id }}-1"><span> </span> </label>
<input type="radio" name="{{ $question->id }}" id="{{ $question->id }}-2" class="color-center" value="0" checked />
<label for="{{ $question->id }}-2"><span> </span></label>
<input type="radio" name="{{ $question->id }}" id="{{ $question->id }}-3" class="color-right" value="-1" />
<label for="{{ $question->id }}-3">{{$question->title}}</label>
</p>
@elseif ($question->question_type === 'likert')
<p class="range-field">
<input type="range" name="{{ $question->id }}" id="{{ $question->id }}" min="1" max="5"/>
</p>
@endif
@if ($question->pos == $last_question->pos )
<div class="row">
{{ Form::submit('Klaar!', array('class'=>'btn waves-effect waves-light finish-button')) }}
{!! Form::close() !!}
</div>
@endif
@if ($question->question_type != 'kleurvraag' AND $question->question_type != 'sectionend')
</div><!-- div end question-->
@endif
@endforeach
</div><!-- div end for tab -->
<?php $inc++; ?>
@endforeach
<div class="row">
<div class="col s12">
<ul class="tabs" style="text-align:center;">
<?php
$count = count($section_array);
for($i = 0; $i < round($count); $i++){ ?>
<li class="tab" id="tab<?=$i;?>" style=""><a class="hide-tab" href="#sales-<?= $i;?>">Sectie</a></li>
<?php } ?>
</ul>
</div>
</div>
</div>
</div>
I thought about dumping all question types in an array, loop through that and place each question in a separate blade file. Is that the way to go?
But how would you guys refactor this into a better workable solution?
Thanks in advance
@Robbus Maybe have the question model responsible for returning the view that should be used to render it. You can then just loop over your questions and include the view like this:
class Question extends Model
{
public function viewName()
{
return 'question-types.'.$this->type; // i.e. question-types.radio
}
}
@foreach ($questions as $question)
@include ($question->viewName())
@endforeach
Each question type would then have its own mark-up separated into various includes.
@martinbean
And then create a separate file foreach question? I think i'll do that first. Would you think this problem is better solved with other technology? Perhaps Vue?
@Robbus Yeah, you would have a file for each question type, that has the mark-up for that question type only.
Technology isn’t really the issue here. It’s just the less conditionals in your views, the better.
Please sign in or create an account to participate in this conversation.