Laravel nested select and conditional statement in view blade - html

So I've succeeded to make a calendar display for the current month. This time, I want to show event details for a specific date. I'm not sure how to get the $event data where $event == $date.
This is the controller. I have event and dates to be used in the view:
$event = Event::where("started_at", '>=', Carbon::now()->subDays(30)->toDateTimeString())
->orderBy("started_at", "asc")
->first();
$data["event"] = $event;
$data["month"] = Carbon::now()->month;
$data["dates"] = range('1', date('t'));
return view('event.all', $data);
This is the event.all view:
#foreach($dates as $date)
<div class="seven-cols">
<div class="titlehead">
<h6>{{$date}}</h6>
<h6 style="color: lightgrey;">{{date("D", mktime(0, 0, 0, $month, $date))}}</h6>
<div style=" ">{{$eventdate = date('d',strtotime(#$event->started_at))}}</div>
#if($event->started_at == $date)
<div>Test</div>
#endif
</div>
</div>
#endforeach
What I got for this code:

As this other answer suggests I would use CarbonPeriod (or create a range with a loop if CarbonPeriod not available for you) and then collect the events for each date at the same time.
As a good practice, we should avoid keeping too much logic inside the templates and therefore build as much as we can of the content before actually building the template itself.
Using your example, and assuming that you only want to show one event for each day we could have something like this:
(Not tested code though)
$startDate = Carbon::now()->subDays(30)->toDateTimeString();
$endDate = Carbon::now()->toDateTimeString();
// Narrow down the list from the database
$events = Event::whereBetween("started_at", [$startDate, $endDate])
->orderBy("started_at")
->get();
$data = CarbonPeriod::create(
$startDate,
$endDate
)
->map(function(Carbon $date) {
$event = $events
->where("started_at", $date->toDateTimeString())
->first();
return [
"date" => $date,
"event" => $event,
];
});
return view('event.all', $data);
And in the template:
#foreach($data as $day)
<div class="seven-cols">
<div class="titlehead">
<h6>{{$day["date"]->day}}</h6>
<h6 style="color: lightgrey;">{{$day["date"]->format("D")}}</h6>
<div style=" ">{{$day["date"]->format("d")}}</div>
#if(!is_null($day["event"]))
<div>{{$day["event"]->someTextField}}</div>
#endif
</div>
</div>
</div>
#endforeach
I hope it helps!

Related

Add block after 3rd list item in a yii2 listview widget

I have not worked with the listview widget before so I cant find a solution for this, as I output a list with items I wanted to do 2 things, 1. auto increment and unique ID/number to each list item, 2. add a block(custom piece of code) after each 3rd list item.
I could not find any documentation about this so not sure if this is possible.
echo ListView::widget([
'id' => 'listofitems',
'dataProvider' => $dataProvider
]);
<div id="listofitems">
<div class="list_item_wrapper">
// my items which are in a seperate file
<div class="list_item_wrapper">
// when using the $index to check for a certain number the code will be build here.
</div>
</div>
// the needed solution
if($index == 12 || $index == 12){
echo 'some div here';
}
</div>
You can use the itemView option for the ListView widget where you can either provide
Specify as a callback function ($model , $key , $index , $widget) { and add your custom HTML inside and do your custom operations like check every third item,or use the actual id by calling $model->id and appending it with the html tag attribute, it provides you
$model: mixed, the data model
$key: mixed, the key value associated with the data item
$index: integer, the zero-based index of the data item in the items array returned by $dataProvider.
$widget: ListView, this widget instance
For example
echo ListView::widget([
'id' => 'listofitems',
'dataProvider' => $dataProvider,
'itemView'=>function ($model , $key , $index , $widget) {
//Do your Thing with Html you want to draw
//return '<div></div>';
}
]);
Or provide the view file path to the option, you can still use the above given params in the view file
For Example
echo ListView::widget([
'id' => 'listofitems',
'dataProvider' => $dataProvider,
'itemView'=>'_view-name'
]);
Your view can look like
<?php
use yii\helpers\Html;
?>
<div class="card">
<div class="header">
<h3 class="title"><?= Html::encode ( $model->title ) ?></h3>
</div>
<div class="body"><img src="<?= Html::encode ( $model->name ) ?>"><?= Html::encode ( $model->id ) ?></div>
<div class="footer"></div>
</div>
UPDATE
If your requirements are to draw or add an element after every item or any number of items you can use the afterItem option which takes an anonymous function that is called once AFTER rendering each data model, it passes same set of parameters as beforeItem
$model: the current data model being rendered
$key: the key value associated with the current data model
$index: the zero-based index of the data model in the model array returned by $dataProvider
$widget: the ListView object
UPDATE2
The below should work in your case with the given HTML
<div id="listofitems">
<?php
echo ListView::widget ( [
'id' => 'listofitems' ,
'dataProvider' => $dataProvider ,
'afterItem=' > function($model , $key , $index , $widget) {
// the needed solution
if ( $index == 12 || $index == 12 ) {
return 'some div here';
}
} ,
'itemView' => function ($model , $key , $index , $widget) {
//Do your Thing with Html you want to draw
return '<div class="list_item_wrapper">
// my items which are in a seperate file
<div class="list_item_wrapper">
// when using the $index to check for a certain number the code will be build here.
</div>
</div>
';
}
] );
?>
</div>
There is such an index by default in the widget. Configure the 'itemView' attribute of the ListView widget, that means you can use a custom view which will be rendered for each item. Like this:
<?= ListView::widget([
'id' => 'listofitems',
'dataProvider' => $dataProvider,
'itemView' => '/site/item',
?>
in your view file /site/item.php, you can access the index of the current item:
<?php
var_dump($index);
?>
More info about the itemView property here.

How to pass a value from controller in a button to the next blade?

I want to pass the value from this controller:
public function show($id)
{
$data_show = DB::select("SELECT * FROM staffs WHERE id = ?", [$id]);
$data_profil = DB::select("SELECT id FROM staffs WHERE id = ?", [$id]);
return view('keluarga.index', compact('data_show', 'data_profil'));
}
Passing the value to this blade:
<div class="row">
<div class="form-group">
<!--add new button -->
<div class="col-lg-2">
{!! Form::open(['route' => 'addkeluarga_form', $data_profil->id]) !!}
{{ Form::submit('Add New', ['class' => 'btn btn-primary']) }}
{!! Form::close() !!}
</div>
<!-- show all button -->
<div class="col-lg-1">
{{ Form::submit('Delete', ['class' => 'btn btn-danger']) }}
</div>
<div class="col-lg-1">
{{ Form::submit('Cancel', ['class' => 'btn btn-warning']) }}
</div>
</div>
</div>
This is add new button which bring the staff id to the add new blade. But it fail to read the value of id in the blade.
How to fix this?
It would be easier to write
$data_profil = DB::table("staffs")->select("id")->whereId($id)->first();
BUT it doesn't make any sense, as you already have $id in your controller. There is no point on retrieving it again from the DB.
Pass $id to the template and use it instead
return view( 'keluarga.index', compact('data_show', 'id') );
check if the data_profil variable is containing your expectation using the print_r() method. i.e
$data_profil = DB::select("SELECT id FROM staffs WHERE id = ?", [$id]);
print_r($data_profil);//you will comment this out latter
check on the top of your page the content of your variable, I you see a nested array output like Array ( [0] => stdClass Object ( [id] => 1 , ...)) , then you may want to refer your variable as an array in your template. i.e.
$data_profil[0]->id
For the first query get all column,
and for secound query I don't think that you need to get id, as you already have id.
$data_show = DB::table("staffs")->where('id',$id)->first();
$data_profil = $data_show->id;
OR
$id = $id; // As the same id it will return
return view('keluarga.index', compact('data_show', 'data_profil','id'));

Yii2 DynamicForm: Demo 3: Nested Dynamic Form with types of rooms

Is it possible to have differents types of rooms in the "demo 3: Nested Dynamic Form" and get the rooms separated by their type? For example, if I wanna create the same as the demo 3 shows and adding a type for each room. I want to have rooms type A, rooms type B and rooms type C. Is it possible? (types are preloaded in the database, the user doesn't have to insert a new type nor select one type. If I want to insert a "room type A", I just add it where it belongs)
I've changed the html but the room's array in the controller didn't has all the rooms (because the first ones are overwritten). So, what do I have to do to make it work fine?
In the picture you can see the approach, I want to make it work because by just editing the html didn't work.
Ok, here is my solution:
Create 2 more clases extended of "Model". So I have 3 clases: Room (ActiveRecord), RoomB (Model), RoomC (Model). So I can representate the 3 types of room.
The attributes of the two "Model" clases, are the "id" and the "description" of the "ActiveRecord" class (remember, we are talking about Room).
In the "_form.php", I've put two "render('_form-rooms')" more, inside divs with class "col-md-4" to get the separation.
<td>
<div class="row">
<div class="col-md-4">
<?= $this->render('_form-rooms', [
'form' => $form,
'indexHouse' => $indexHouse,
'modelsRoom' => $modelsRoom[$indexHouse],
]) ?>
<button type="button" class="remove-house btn btn-danger btn-xs"><span class="fa fa-minus"></span></button>
</div>
<div class="col-md-4">
<?= $this->render('_form-rooms', [
'form' => $form,
'indexHouse' => $indexHouse,
'modelsRoom' => $modelsRoomB[$indexHouse],
]) ?>
<button type="button" class="remove-house btn btn-danger btn-xs"><span class="fa fa-minus"></span></button>
</div>
<div class="col-md-4">
<?= $this->render('_form-rooms', [
'form' => $form,
'indexHouse' => $indexHouse,
'modelsRoom' => $modelsRoomC[$indexHouse],
]) ?>
<button type="button" class="remove-house btn btn-danger btn-xs"><span class="fa fa-minus"></span></button>
</div>
</div>
</td>
In the "actionCreate", I've made 2 extra arrays representing the 2 "Model" clases, so I have those 3 arrays: $modelsRoom = [[new Room]]; $modelsRoomB = [[new RoomB]]; $modelsRoomC = [[new RoomC]];
I've changed all the logic of the code inside "actionCreate" ad hoc with the two extra arrays, so, for example, in the "isset($_POST['Room'][0][0])", I've asking for "isset($_POST['RoomB'][0][0])" and "isset($_POST['RoomC'][0][0])" as well:
// validate person and houses models
$valid = $modelPerson->validate();
$valid = Model::validateMultiple($modelsHouse) && $valid;
$valid2 = $valid3 = $valid;
if (isset($_POST['Room'][0][0])) {
foreach ($_POST['Room'] as $indexHouse => $rooms) {
foreach ($rooms as $indexRoom => $room) {
$data['Room'] = $room;
$modelRoom = new Room;
$modelRoom->load($data);
$modelsRoom[$indexHouse][$indexRoom] = $modelRoom;
$valid = $modelRoom->validate();
}
}
}
if (isset($_POST['RoomB'][0][0])) {
foreach ($_POST['RoomB'] as $indexHouse => $rooms) {
foreach ($rooms as $indexRoom => $room) {
$data['Room'] = $room;
$modelRoom = new Room;
$modelRoom->load($data);
$modelsRoomB[$indexHouse][$indexRoom] = $modelRoom;
$valid2 = $modelRoom->validate();
}
}
}
if (isset($_POST['RoomC'][0][0])) {
foreach ($_POST['RoomC'] as $indexHouse => $rooms) {
foreach ($rooms as $indexRoom => $room) {
$data['Room'] = $room;
$modelRoom = new Room;
$modelRoom->load($data);
$modelsRoomC[$indexHouse][$indexRoom] = $modelRoom;
$valid3 = $modelRoom->validate();
}
}
}
so I ask if the 2 extra "valid" variables are true to continue
if ($valid && $valid2 && $valid3) {
$transaction = Yii::$app->db->beginTransaction();
try {
if ($flag = $modelPerson->save(false)) {
foreach ($modelsHouse as $indexHouse => $modelHouse) {
if ($flag === false) {
break;
}
... (continue with the same code)
and, in the render of the form, I've pass as a parameter the extra arrays created:
return $this->render('create', [
'modelPerson' => $modelPerson,
'modelsHouse' => (empty($modelsHouse)) ? [new House] : $modelsHouse,
'modelsRoom' => (empty($modelsRoom)) ? [[new Room]] : $modelsRoom,
'modelsRoomB' => (empty($modelsRoomB)) ? [[new RoomB]] : $modelsRoomB,
'modelsRoomC' => (empty($modelsRoomC)) ? [[new RoomC]] : $modelsRoomC,
]);
In the "_form.php" view, you can see the code above, I've used the two extra arrays in the render of the two extra "_form-rooms".
In the "_form-rooms", I've removed the code representing the model's id, because in the "actionUpdate", I've remove all the "Houses", so, all their "rooms" will be deleted too. After this, I've just do the same as in the "actionCreate" (after the post).
I hope you can understand my solution. It maybe not the best solution, but it works for me. There are more details that I've omited to not to extend too much this reply, but you can always contact me ;)
If you need more details, email me.

Laravel - Foreach value in php tags with blade template

I have trouble with that, let me explain.
In controller, I get users.
$users = User::where('steamid','!=','')->orderBy('time','DESC')->get();
After that in Blade template I need to use PHP function for the get steam profile link from steam id.
I have a function:
function SteamName($steamid){
$xml = simplexml_load_file("http://steamcommunity.com/profiles/$steamid/?xml=1");//link to user xmla
$username = $xml->steamID;
return $username;
}
I have a foreach for every user:
#foreach($users as $user)
//so, i need to do like this;
<?php print SteamName($user->steamid) ?>
#endforeach
Put your function inside User Model
function SteamName($steamid){
$xml = simplexml_load_file("http://steamcommunity.com/profiles/$steamid/?xml=1");//link to user xmla
$username = $xml->steamID;
return $username;
}
From Your blade call the function :
#foreach($users as $user)
{{ $user->SteamName($user->steamid) }}
#endforeach
You can also try this
#foreach ($users as $user)
{{$user->steamid}}
#endforeach

Yii2: getting error while page load '$model not defined'

I have developed form to allow owner to create team. code is:
<?php $form = ActiveForm::begin(['id' => 'team-create-form', 'action' => ['site/create-team-form'], 'options' => array('role' => 'form')]);
<div class="col-lg-10 form-group" id="createTeamForm" style="margin-top: 15px;">
<div class="col-lg-4">
<?= $form->field($model, 'team_name',['template' => "{label}\t{input}\n{error}"])->textInput(array('placeholder'=>'Enter team name....')); ?>
</div>
<div class="col-lg-4">
<?= $form->field($model, 'team_description',['template' => "{label}\t{input}\n{error}"])->textInput(array('placeholder'=>'Enter team Description....')); ?>
</div>
<div class="col-lg-2">
<?= Html::submitButton('Submit', ['class' => 'btn btn-danger', 'id' => 'tsubmit', 'style' => 'margin-top: 22.5px; margin-right: 15px;']) ?>
</div>
</div>
I have tried loading the page with the above code but it is showing me error "$model not defined". How to resolve that. Am i need to add something in the main-local.php???
public function actionLogin()
{
$model = new LoginForm();
$session = Yii::$app->session;
if ($model->load(Yii::$app->request->post()) && $model->login()) {
$collection1 = Yii::$app->mongodb->getCollection('users');
$teamid = $collection1->findOne(array('username' => $model->email_address));
$session->set('id', $teamid['_id']);
$session->set('name', $teamid['name']);
$session->set('username', $model->email_address);
$collection2 = Yii::$app->mongodb->getCollection('teamdashboard');
$teams = $collection2->find(array('admin' => $model->email_address));
$model1 = new TeamCreateForm();
return $this->render('dashboard', ['model'=>$model1, 'teams'=> $teams]);
} elseif($session->isActive){
$username = $session->get('username');
$collection = Yii::$app->mongodb->getCollection('users');
$teams = $collection->findOne(array('username' => $username));
return $this->render('dashboard', ['teams'=>$teams]);
}else{
$this->layout = 'index';
return $this->render('login', ['model' => $model]);
}
}
I have renamed the productpage as dashboard for better understanding.
Now when i run this & logs in, The address bar url shows url:..../web/index.php?r=site/login whereas it should show me url:..../web/index.php?r=site/dashboard & shows me the view of dashboard.
When i refresh the page, i brings me back to the login...
Did you use $model in dashboard view? If you do - you need to pass it (the same way as the login).
You have to send the $model to the view. The view only knows variables if you send it to it.
I have no idea what you mean with the address bar. The address bar has nothing to do with what you send to the view.
EDIT
Your entire way of thinking is strange. Why would u show different views depending if the person is registered or not?
return $this->render('dashboard', ['teams'=>$teams]);
return $this->render('login', ['model' => $model]);
User redirect with parameters to move the customer to another page. Having an URL like /login that actually shows a dashboard is not logical.