I'm trying to integrate Laravel with React that has multiple hierarchical components. However, I don't want these components to be bundled in one single view. How I view it, the current capability of Laravel is to route a single view to one single request. My react component hierarchy is as follows:
Main React App
├─ Subcomponent A
└─ Subcomponent B
However, I only want to fetch each of the subcomponents at certain events in the Main React App. Specifically, I want to get the subcomponents from the server only if the subcomponent will be included in the DOM tree. The fetching must be done with Laravel views.
Is it possible to implement this with Laravel and React?
It is possible, but you will need to manually create Laravel web routes that will allow you to fetch the components. For instance, if Component A requires Component B from server, a web route (or a shared web route) must be made. Here's a demo:
/routes/web.php
// the route which returns your react app engine
Route::get('home-page', function(){
return view('home_page');
});
// the route used to fetch components dynamically
Route::get('react-components/{component_name}', function($component_name){
// you can either wrap your components in blade files
return view('react_components.'.$component_name);
// or manually read them from disk and return them as plain-text responses
return response(
// you can use Storage facade: https://laravel.com/docs/7.x/filesystem
\Storage::disk('react_comps')->get($component_name)
// or primitive method
file_get_contents(base_path().'/views/assets/react_comps/'.$component_name)
);
});
Then, when you want to fetch the component, use the route:
axios.get('/react-components/posts.js')
.then(res=>{
// do stuff with res.data
})
Related
I can't undestand how to create a new Vue component inside my app created with Laravel and Inertia.
The problem is that I can't make a call from the component to an API (in the routes/api.php file) that is protected by an auth middleware (like auth:api).
There is a practical example:
I manage a list of customers in my app. Then I manage invoices. So, in the invoice creation form I must select one of the customers in my database. I want to make a componente (like <SelectCustomer v-model="form.customer" /> maybe) where inside itself I can make an API call that return the list of all customers to populate my select.
Obviously, that API is reserved only for the logged user, so has a middleware guard.
It's possible to make an axios call - maybe - in the component's methods? but with what informations? maybe I must obtain a bearer token?
I am learning Angular 7 by studying this example app. The example app uses a wildcard route to handle all otherwise-unhandled routes.
Specifically, this app-routing.module.ts directs all miscellaneous routes to AppConfig.routes.error404, which is handled by Error404PageComponent.ts, which then ultimately serves up error404-page.component.html for every possible route that is not specified by its own component and named route.
What specific changes would need to be made to the code in this sample app in order for the wildcard route serve different static content for different submitted routes?
For example, if a web user typed in the route /i-am-a-jelly-donut, what changes would need to be made so that the request would 1.) continue to go through Error404PageComponent.ts, but have the user's browser receive a new i-am-a-jelly-donut.page.html instead of the error404-page.component.html view?
The Error404PageComponent.ts would still serve up error404-page.component.html for every non-specified route. However, we would be adding logic to give special handling inside Error404PageComponent for a specific static route in addition to the logic for every non-specified route.
The goal here is to be able to handle static routes without having to create a separate component for each and every route. Think, for example, of a blog where most of the routes have an identical template, but with different content in each blog entry.
Templates are compiled into the components at build time and you are not going to be able to change which template a component uses at runtime but you can hide and show sections based on conditions. Inject the router into your component
constructor(private router: Router) {}
Now you can set a variable on your component based on if the route contains 'i-am-a-jelly-donut'
jellyDonut = this.router.url.indexOf('i-am-a-jelly-donut') !== -1;
and in your template
<ng-container *ngIf="jellyDonut">
Jelly Donut
</ngcontainer>
<ng-container *ngIf="!jellyDonut">
Other stuff
</ngcontainer>
I am using Laravel Nova custom tool which uses vue js for custom functionalities.
There is a tool.vue file inside of the component after creation, that everything handles there. The thing is I would like to have different templates (vue files) and render them whenever they are needed.
In this case my main tool.vue is a search with dropdowns which I completely implemented. But I want to render the list of the results from a different vue file after clicking on a button. (of course the other vue file will consist of a table or something to show the data).
The question is how to handle this with vue js and how can I change between components ? and how can I pass paramters/data from the main vue file into the result page so I can do ajax requests or etc.
You might want to use a good router for handling the pages dynamically and in SPA format. Seems like Laravel Nova is using vue-router.
It is installed under the custom component as you create it and if you want to use other vue files or switch between them, you need to add your route under nova-components\[your-component-name]\resources\js\tool.js file by adding an object into the array of routes in this format:
{
name: '[route-name]',
path: '/[route-path]/:[sent-prop-name]',
component: require('./components/[your-vue-file]'),
props: route => {
return {
[sent-prop-name]: route.params.[sent-prop-name]
}
}
},
After adding the router to this file you can always use <router-link></router-link> component inside your Vue files to redirect to whatever route you desire (you can also send data to the route as props). The main format of it is like this:
<router-link
class="btn btn-default btn-primary"
target="_blank"
:to="{
name: '[destination-route-name]',
params: {
[your-data-name]: [your-data-value]
}
}"
:title="__('[your-title]')"
>
Submit
</router-link>
P.S: Of course you can omit props and params from both if you don't intend to send and receive any data to the file.
P.S: You can always take look at vue-router documentation here for more features.
I'm trying to build a E-Commerce Store and it requires that I initially load a list of trending products on the home page.
Here, I can simply do without redux and simply display the data (roughly) of this sort
const trendingProducts = await get('/api/trendingProducts')
render(){
<TrendingProducts data={this.trendingProducts.data} />
}
I am using redux in my application. So should I do a dispatch elsewhere to fetch the trending products ?
All in all, Should I always handle every single fetch / render using only Redux dispatch ?
Redux is a store management for your application's state. Redux's dispatch is used to dispatching actions that aims to update your application's state in some way.
Hence if your application logic requires displaying information that belongs to your application's state - you need to take it from Redux store. If such information is not yet available into Redux store - you need to obtain it from some source (e.g. fetch) and use dispatch to update your application's state. If information, you're trying to display is not part of your application's state - you can display it directly, but in this case you'll need to handle React lifecycle events by yourself too since React re-draws components upon component's state change.
UPDATE: Your example code will work fine if you'll put your trendingProducts into component's state:
class MyComponent {
constructor() {
super();
this.state = {
trendingProducts: {}
}
}
componentWillMount() {
fetch('/api/trendingProducts').then(data => this.setState({trendingProducts: data}));
}
render() {
return (
<TrendingProducts data={this.state.trendingProducts}/>
)
}
}
That is very subjective and there is no correct answer but I can tell you by my experience.
Always keep your business logic separate from your component
If you're making API calls then you should definitely dispatch an action rather writing this in your component because there are lot of redux-like stores are emerging and it might happen that later you want to change your store using some different architecture. Your view layer should be independent on your API calls (business logic). In this way, while refactoring your app again, you'll just have to change the logic and your view will remain the same.
I'm writing this on my experience where we started refactoring the whole app from backbone to React. We had models and collections, we changed the whole html but we didn't change any business logic initially, just the views were deprecated but later we removed the business logic too using redux (iteratively). You should write your code in such a way that it has maximum reusability after all that's what React is and that's how you should write your front-end code.
Also, the component's state can reside in component where the whole app doesn't get affected. e.g. showing or hiding of a third-pane or overlay etc.
I have created a new api using sails sails generate api tasks, using the default configuration of sails 0.12.
With Sails awesome blueprints, I can access localhost:1337/tasks and see the list of tasks or localhost:1337/tasks/create?text=yo to create a new one.
But what I want it to connect these endpoints to an .ejs view.
I tried creating a new folder tasks and placing show.ejs or index.ejs files in it but it's still returning the Json.
Is there a default way to render .ejs files through the default blueprint urls, without creating new routes and controller methods?
Well it took me a while to find the answer, so for anyone looking to use sails.js development speed, here is the way to do it:
After generating the api, create a folder inside your views folder (named after your controller). The files in it should be:
+ tasks (the folder with the same name as your controller)
- find.ejs (list of all items)
- findOne.ejs (view a specific item)
- create.ejs (after a successful creation)
- update.ejs (after a successful update)
- destroy.ejs (after a successful deletion)
These files are connected by default to the different api endpoints. So, when you access the url localhost:1337/tasks sails will automatically render tasks/find.ejs. Same for the other endpoints.
Another point is that each view will have a global variable named data that will include the result of the api request (i.e. the records that were fetched / modified).
You can see a small example here: https://github.com/web-development-course/Bootstrap (look at the 'things' api)
I hope it will help you guys