Using a Blade directive in a Blade directive - laravel

I'm using Laravel 5.1. I am trying to use a Blade directive (#extend) with my custom Blade directive.
Blade::directive('base', function() use ($theme) {
return "#extends($theme)"
});
However, the above code only literally displays the contents (#extends($theme))

Contrary to a comment I made earlier, I think this is possible (but untested) using the blade compiler.
Blade::directive('base', function() use ($theme) {
return Blade::compileString("#extends({$theme})");
});

Related

Vue2 + laravel6 - Component implementation

I just started using Vue2 with Laravel6 and got stuck when trying to understand how to use component method.
As I am totally new for Vue, I am using the official tutorial of Vue as a reference. What I learned from here(https://v2.vuejs.org/v2/guide/components.html) about Vue component instantiation is we give options to a component.(e.g. we give 'template:' options for HTML part.)
When I look at laravel6 codes of resouces/js/app.js, it looks something like this:
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
I looked at js/components/ExampleComponent.vue expecting to see some options declared there. However, there's no option in the ExampleComponent.vue file. Instead, I see <template></template> tag. Apparently, the <template></template> tag seems to work as 'template:' option.
I have two questions regarding above:
Does <template></template> tag have the same meaning as 'template:' option?
If question 1 is yes, are other options also replacable with corresponding tags? (e.g. Can I use <props></props> tag for 'props:' option? or <data></data> tag for 'data:' option?
Thanks in advance!
In Vue world, there are two popular types of defining a component
First Type
in this type, you add all of your HTML inside the template property
and the props add as attribute inside the component object to
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
Second Type
in this type you add your component logic in a separate file ends with .vue
for example in laravel there is an ExampleComponent.vue file you will find on
it just template tag just as a wrapper for your component content and your logic you can write it as it mentions below.
<template>
// some content here
</template>
<script>
export default {
props: [],
methods: {
},
data(){
return {
}
}
}
</script>
Finally
there is no tag called props or data
for more info read this article

call to ReactJS component in Laravel blade templates

I use Laravel 5.4 and React 15.5.4, code is writing in ES6.
I'd like replace Vue and use React and I did it. But I often will use small components for example 2 in different places of blade template. I don't want use one app component.
I'd like use something like:
<span class="react">
<TestComponent property={true} />
</span>
I can't do it automatically. Now I use
<span data-component="TestComponent" data-props="{property:true}" />
and in app.js
_.each(document.querySelectorAll('[data-react]'), element => {
let props ={};
Array.prototype.slice.call(element.attributes)
.forEach(item => {
props[item.name] = item.value;
if(item.name !== 'data-react'){
element.removeAttribute(item.name);
}
});
ReactDOM.render(React.createElement(reactComponents[element.getAttribute('data-react')],props),element);
});
It works but I need to use add all properties to one react component property and then use for example this.props.out.propery
I also would like set normal component tag in my blade component
I've try to use in app.js
_.each(document.querySelectorAll('.react'), item => {
ReactDOM.render(item.children,item);
});
Someone have any idea to solve this problem?
EDIT
I changed my solution to:
<span data-react="LoginForm" input="{{json(request()->old())}}" error="{{session('error')}}" errors="{{json($errors->getMessages())}}" />
or
<LoginForm data-react="LoginForm" input="{{json(request()->old())}}" error="{{session('error')}}" errors="{{json($errors->getMessages())}}" />
in blade and in resources/assets/js/app.js
var reactComponents = {
LoginForm: require('./components/login').default,
};
_.each(document.querySelectorAll('[data-react]'), element => {
let props ={};
Array.prototype.slice.call(element.attributes)
.forEach(item => {
props[item.name] = item.value;
});
ReactDOM.render(React.createElement(reactComponents[element.getAttribute('data-react')],props),element);
});
It works fine. This is not super clear solution but I have impression that the reasonable.
I can set components name in html code and add props almost same like in JSX.
As far as I know, you can not mix JSX components directly with Blade templates. The only server side rendering available today for React is NodeJS.
What you could do to improve your architecture is add specific HTML tags with certain ids and render the react components in them. So inside Blade you could do something like:
<div id="componentA"></div>
This will act as a place holder in your Blade template for that react component. Then you render your componentA from your app.js like this:
React.render(<ComponentA prop1='valueX'/>, document.getElementById("componentA"))
Remember that in this case the world of react and world of Blade run at different times.
You could use document.getElementsByTagName('LoginForm') getting all the instances and later iterate its attributes. It's clear code but not generic, because it will work just for LoginForm components.
If you want to render any tag name, then maybe it's better to use some attribute as you used with data-react.
getElementsByTagName isn't super supported by old browsers so maybe could a good idea to use jQuery as fallback $('LoginForm')

Blade templating with angular2 templating?

I have problem because im using angular with laravel.I added this in routes.php
Blade::setContentTags('<%', '%>'); // for variables and all things Blade
Blade::setEscapedContentTags('<%%', '%%>'); // for escaped data
But its not working because im getting an error when i display data from angular.
Any suggestion how can i fix this?
For example if i say:
{{'test'}} it works but if i say {{response.test}} where response is from angular i get an error because laravel thinks that is his.
Blade will ignore anything preceded by the # character. Try that.
first confing laravel blade and angular js
<script type="text/javascript">
var app = angular.module('myApp', [])
.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('<%=');
$interpolateProvider.endSymbol('%>');
});
</script>
write your angular code like this
<%= cs.Category_name %>

How to pass javascript variable from laravel controller to vuejs component

I'm trying to build a page on Laravel 5.4 which contains few data which needs to be manipulated and then sent across the views. My view contains components of the vuejs v2.0. I want those data to be implemented in the components. I tried using the laracasts PHP Vars to JS transformer but unable to get it. I followed the steps by placing "laracasts/utilities": "~2.0" in my composer.json then I added the serviceprovider as mentioned in the documentation, I published the vendor and added the following in config/javascript.php,
'bind_js_vars_to_this_view' => 'Nitseditor.show',
I'm having a dynamic views folder which is currently inside my Nitseditor\home\resources\views Now in my controller I'm having following codes:
public function show()
{
JavaScript::put([
'foo' => 'bar',
'age' => 29
]);
return view(Nitseditor.show);
}
Now first of all it was throwing an error as I see that it was including use MongoDB\BSON\Javascript; then I removed and tried using use JavaScript
Now in the app.js file which is present in my asset folder, I'm including each components and trying to do console.log(foo); but its throwing an error foo not defined.
There are a few ways to do this depending on what you are trying to achieve and how your project is set up. The simplest way is to make a request to your controller from inside your component that returns json. Laravel 5.4 comes with axios so you can use that:
methods: {
getData(){
axios.get('/controller/route')
.then(response => {
// set your variables from the response
this.myData = response.data;
})
.catch(error => {
console.log(error);
});
},
data(){
return {
myData: {}
}
}
If you need child components to access the data then you would need to put that in the parent and pass myData" using props.
You could also create a directive and pass your variable down directly from your blade template:
Vue.directive('init', {
bind: function(el, binding, vnode) {
vnode.context[binding.arg] = binding.value;
}
});
Then you would just need to do:
<div v-init:vars="{foo: 'foo', age: 29}"></div>
And pass vars as props to any component that needs them:
Here's the JSFiddle: https://jsfiddle.net/3e05qwLh/
If you have multiple descendants that rely on your variables you will probably want to look at using vuex.
Dunno if it helps but I use this method for passing variables to javascript:
// in master layout (head section)
<meta name="foo" content="{{ $foo }}">
// in javascript (included or in the template)
foo = $('meta[name=foo]').attr('content');
If you have javascript in the blade template you can use directly this method:
foo = "{{ $foo }}";

Laravel - header/footer includes in views?

I am new to Laravel, I would like to create my layout without using blade.
I have created a header.php view and a footer.php view.
In the filters.php file, I did this:
App::before(function($request)
{
return View::make('layout/top');
//
});
App::after(function($request, $response)
{
return View::make('layout/bot');
//
});
And in my routes:
Route::get('/', function()
{
return View::make('hello');
});
The header displays fine...but not the hello view or footer view.
What am I doing wrong?
Consider rendering your header and footer views to a variable, and then passing that to your content view. This also allows you to pass in extra data such as meta, js, styles, etc. that may be unique to the page your delivering to the DOM.
$data['header'] = View::make('templates/header')->render();
$data['footer'] = View::make('templates/footer')->render();
return View::make('myview', $data);
I believe App::after gets fired after the request: application-events
Myself, I use a single template (blade) which has a placeholder for content - You can use standard php in a blade template and this seams to give me more flexibility than controller layouts: templating

Resources