HTML output with spaces in laravel - laravel

I've never met this behaviour while working with laravel, but now I got something annoying. I have this code:
<span class="category-list">
(#foreach ($material->categories as $category)
{{ $category->name }}
#endforeach) )
</span>
And I got this output:
As you can see I got a lot of spaces here. I suppose that's because I have tabs in my code (tabs automatically converted to spaces in phpstorm). But how to deal with it except having ugly code without spaces?
I think I'm missing something simple as I've never had such trouble

Where is this data coming from? What happens when you dump this from your controller? (still extra whitespace?)
If the whitespace is indeed in the property itself and it serves a purpose, you could make a Macro to trim() it, or trim() it in-line.
trim():
<span class="category-list">
(#foreach ($material->categories as $category)
{{ trim($category->name) }}
#endforeach) )
</span>
Or Macro:
Macro: (register the macro)
Form::macro('trimWhitespace', function($val)
{
// do anything you want to $val.
return trim($val);
});
View: (use the macro)
<span class="category-list">
(#foreach ($material->categories as $category)
{{ Form::trimWhitespace($category->name) }}
#endforeach) )
</span>

Related

AlpineJS inline function and Laravel #json

I have a problem passing a PHP variable to a variable inside an alpine variable or function. Here is a simple example.
#php
$test = "Hello World's testing";
#endphp
<div x-data="{
message: #json($test)
}">
<span x-text="message"></span>
</div>
The problem comes from the fact that x-data is using the double-quote to wrap the encoded data. I know I could "externalize" the x-data, but I really need it to be inline.
I have a basic workaround (using backticks) for example, but I wanted to know if there is a better way to do this.
EDIT
The example is using a string... but the PHP variable can be a boolean or even an array. That's why I'm using #json.
I' d use Template Strings.. Easy to read, no need to escape multiple quotes.
<div>
#php
$test = "Hello World's testing";
#endphp
<div x-data="{
message: `{{ $test }}`
}">
<span x-text="message"></span>
</div>
</div>
Will this not work?:
#php
$test = "Hello World's testing";
#endphp
<div x-data="{
message: {{ json_encode($test) }}
}">
<span x-text="message"></span>
</div>

Laravel Components: default content in {{ slots }}

In old-style Laravel blade templated we used to use #section('section-name') in the following way:
{{-- h1para.blade.php --}}
<h1>
#section('heading')
Heading from Template
#endsection
</h1>
<p>
#yield('details')
</p>
And then extend that template with:
{{-- content.blade.php --}}
#extends('h1para')
#section('details')
Content from content page
#endsection
In the above, my rendered HTML output would look like the following, because the "missing" 'heading' section in the extending file means that we default back to the content in the template:
<h1>Heading from Template</h1>
<p>Content from content page</p>
But in the new components way of doing things, I do:
{{-- .../components/h1para.blade.php --}}
<h1>{{ $heading }}</h1>
<p>{{ $slot }}</p>
In case you haven't gathered, the question is: how do I set a default value for a slot's contents, such that if it isn't supplied in the extending component/template, it falls back to that default?
(I've done my searches, but haven't been able to find the same question asked before)
EDIT:
I should add that I've seen the solution (in the Laravel documentation):
<h1>{{ $heading ?? 'Default Heading Here' }}</h1>
But this seems only to be appropriate if the default value is a short easy to manage string. If the default is a long stream of HTML, then it wouldn't work for my needs.
EDIT 2:
Just to reiterate: the whole point of the question is that the default content could be a long stream of HTML. Solving the problem by passing in a string (be that formatted as HTML or not) wouldn't work for my real-world needs.
I think the solution is this:
{{-- .../component/template.blade.php --}}
<div>
#if (isset($heading))
{{ $heading }}
#else
<h1>Default Heading<span class="subhead">default subheadin and lots of other html content</span></h1>
#endif
<p>{{ $slot }}</p>
</div>
It's not super elegant, but I think it's the only solution. Anyone else have a better answer, I'd love to hear it.
If you pass data like:
<x-h1para header="<span>Header content</span>">
<div>Default slot content here</div>
</x-h1para>
You can display in your component like:
<div>
<h1>{!! $heading ?? 'Default Heading Here' !!}</h1>
{{ $slot }}
</div>

Undefined variable: categories in user.blade.php

I was trying to extend my user.blade.php to my views menu.blade.php. Everything works fine with my other views that use the same user.blade.php too. But not with my menu.blade.php, I get an error saying "Undefined variable: categories (View: D:\xampp\htdocs\mieaceh\resources\views\layouts\user.blade.php)" with "Possible typo $categories
Did you mean $errors?"
Here are the codes to my user.blade.php
#foreach($categories as $category)
<a href="{{ route('menu.index', ['category' => $category->slug]) }}">
<div class="card-category" style="width: 10rem; height: 4rem;">
{{ $category->name }}
</div>
</a>
#endforeach
How do I solve it?
If you want to make a piece of view that appears in multiple places, you can use blade components https://laravel.com/docs/8.x/blade#components.
This will help encapsulating this partials behavior and required data.

Too many whitespaces when outputting blade variables?

A bit of background: I'm trying to create user-editable pages in a blog-style web application. The application consists of multiple pages worth of content included into one page; dynamically generated from the back-end and laid out one under the other.
Note: I am a Laravel newbie.
The content of the pages is kept in the DB; one DB record = page title + content. I retrieve all records and send them to the template:
class ContentController extends Controller {
var $current_content;
public function __construct() {
$this->current_content = Content::all();
}
public function serveContent() {
return View::make('home')->with('pages', $this->current_content);
}
}
Over in the template I iterate through the object with the freshly retrieved data and display the contents for each page:
#foreach($pages as $page)
<section class="page">
<div class="editable-page" id="{{ $page->page }}">
{{ $page->content }}
</div>
<div hidden class="editable-page-edit-mode" id="{{ $page->page }}">
<textarea class="page-edit">
{{ $page->content }}
</textarea>
</div>
<input hidden type="button" class="edit-btn" value="Edit {{ $page->page }} section"/>
</section>
#endforeach
(The textarea is for the edit mode, it contains the same content as above; except this time it will be sent back to the DB).
The problem is that when outputting the variable contents with {{ $page->content }}, an absurd amount of whitespaces seem to be introduced.
Here's how the section looks in the browser: http://prntscr.com/bzeu4l
And here's what happens behind the scenes: http://prntscr.com/bzets2
Normally it would be completely and utterly irrelevant to me since the content is displayed properly. But when I unhide the textarea, it's clear that it receives the exact same data, with whitespaces: http://prntscr.com/bzeum8
This is a big problem because I don't want the DB values to be overwritten with spaces.
I could work around this by using regex and stripping what has more than 2 spaces when I save the data. But this feels like a workaround, not a solution.
Does anyone know an elegant solution to this? Since I'm a Laravel newbie, it's very possible that I'm missing something obvious about displaying variable values in Blade.
Thanks in advance.
PS: If anybody has any suggestions about my approach / if my approach with the textarea is flawed, I warmly welcome criticism.
Also, I am terribly sorry for the vague layout of the page, it's still in a very incipient stage. In case it's not evident, 'testhomecontent' and 'testservices' are practically $page[0]->content and $page[1]->content.
In blade when all spaces between the contents are preserved. So, to get rid of spaces change your following code
<div hidden class="editable-page-edit-mode" id="{{ $page->page }}">
<textarea class="page-edit">
{{ $page->content }}
</textarea>
</div>
To this:
<textarea class="page-edit">{{ $page->content }}</textarea>
Change
<textarea class="page-edit">
{{ $page->content }}
</textarea>
To
<textarea class="page-edit">{{ $page->content }}</textarea>

Laravel 4 how to display flash message in view?

I'm trying to get my flash message to display.
This is in my routing file
Route::post('users/groups/save', function(){
return Redirect::to('users/groups')->withInput()->with('success', 'Group Created Successfully.');
});
This is in my view
{{ $success = Session::get('success') }}
#if($success)
<div class="alert-box success">
<h2>{{ $success }}</h2>
</div>
#endif
But nothing is working.
When I try this, I get an error Variable $success is undefined. But it actually shows the flash message too.
{{ Session::get('success') }}
#if($success)
<div class="alert-box success">
<h2>{{ $success }}</h2>
</div>
#endif
This works for me
#if(Session::has('success'))
<div class="alert-box success">
<h2>{{ Session::get('success') }}</h2>
</div>
#endif
if you are using bootstrap-3 try the script below for Alert Style
#if(Session::has('success'))
<div class="alert alert-success">
<h2>{{ Session::get('success') }}</h2>
</div>
#endif
when you set variable or message using ->with() it doesn't set the variable/message in the session flash, rather it creates an variable which is available in your view, so in your case just use $success instead of Session::get('success')
And in case you want to set the message in the session flash the use this Session::flash('key', 'value'); but remember with session flash the data is available only for next request.
Otherwise you can use Session::put('key', 'value'); to store in session
for more info read here
two methods:
Method 1 - if you're using
return Redirect::to('users/groups')->withInput()->with('success', 'Group Created Successfully.');
under your controller create(), add in
$success = Session::get('success');
return View::make('viewfile')->with('success', $success);
then on view page,
#if (isset($success))
{{$success }}
#endif
What's happening in method 1 is that you're creating a variable $success that's passed into your create(), but it has no way of display $success. isset will always fail unless you set a variable to get the message and return it.
Method 2 - use return Redirect withFlashMessage
return Redirect::route('users/groups')->withFlashMessage('Group Created Successfully.');
then on your view page,
#if (Session::has('flash_message'))
{{ Session::get('flash_message') }}
#endif
Method 2 is much cleaner and does not require additional code under create().
{{ Session::get('success') }}
This just echos the session variable 'success'. So when you use
{{ Session::get('success') }}
#if($success)
<div class="alert-box success">
<h2>{{ $success }}</h2>
</div>
#endif
you are seeing it's output along with the error of the next statement. Because with() function only sets the value in Session and will not set as a variable. Hence #if($success) will result in undefined variable error.
As #Andreyco said,
#if(Session::has('success'))
<div class="alert-box success">
<h2>{{ Session::get('success') }}</h2>
</div>
#endif
This should work.
The reason you are not seeing it might be because the action you are performing is not success. And this does not require you to either reinstall xampp or modify php.ini.
Laravel 4.2
Personally i use
Session::flash('key', 'value');
return Redirect::to('some/url');
then in the view id first check if there is a session of that key in the view
#if(Session::has('key'))
{{Session::get('key')}} //this prints out the message or your 'value' in the session::flash method
#endif
it works for me most of the time and i usually have that blade template integrated into my view just so i can push success messages to the view from my codes.
please do note that it is stated in the documentation that "Sometimes you may wish to store items in the session only for the next request. You may do so using the Session::flash method" so yes it expires after the next page.
hope this helps
i just realized in using the Redirect::to(), when you use the withInput() method, chaining a with() function to pass variables will not work. the only way is either you flash your inputs separately using Input::flash(), and use the with() to pass your variables or you pass your variable via session using Session::flash('key','val') and retrieve in the view via session::get('key').
This link describes how to do this http://vegibit.com/flash-messages-in-laravel/
Just tried with laravel 5 - works to me.
Inside of the routes.php file try to create your routes within the
Route::group(['middleware' => ['web']], function () {
//routes here
}
then use
#if(Session::has('success'))
<div class="alert-box success">
<h2>{{ Session::get('success') }}</h2>
</div>
#endif
I fixed mine by changing the session driver in config/session.php from array to file !

Resources