Im using angular-fullstack newest version I think "generatorVersion": "3.7.5", and right now I created a route
yo angular-fullstack:controller products and it created the files:
products.controller.js
products.controller.spec.js
products.js
products.scss
and when I tried
yo angular-fullstack:controller product_new_view
inside the folder /client/app/products it created a new folder
/client/app/products/product_new_view
which I think is ok but the question is why the controller definition is not inside a component as in /client/app/products/products.controller.js
angular.module('meanshopApp')
.component('products', {
templateUrl: 'app/products/templates/products.html',
controller: ProductsComponent
})
})();
instead is just
angular.module('meanshopApp')
.controller('ProductNewViewCtrl', function ($scope) {
$scope.message = 'Hello';
});
does that mean that for every new view I need to create a route? cause I read https://docs.angularjs.org/guide/component and there it says
Components as route templates
Components are also useful as route templates (e.g. when using ngRoute). In a component-based application, every view is a component:
Im new to angular by the way
Related
I’m fairly new to the components & livewire game so I’m getting very confusing when I need to update a component value from other sources. Let me explain:
I’m using a default Laravel 8 installation with Livewire - no JetStream.
My navigation file (the default one that comes with the installation) has 3 individual components containing: total of points achieved, total of lives and remaining lives.
Loads like:
<x-points>0</x-points>
<x-lifes>0</x-lifes>
<x-remaining-lifes>0</x-remainung-lifes>
My question: how do I update any of those components when I execute actions from different sources like:
user answer a question (file Answer.php)
User clicks on an action at the footer of my application (let’s call this Regenerate.php)
User request tips so I need to subtract (Tips.php)
I would change your three main blade components for livewire componentes:
<livewire:points></livewire:points>
<livewire:lifes></livewire:lifes>
<livewire:remaining-lifes></livewire:remaining-lifes>
So for example, let's create the points and answer components.
// Points.php livewire component
public int points = 0;
public $listeners = ['loadUserPoints'];
public function render() { ... }
public function loadUserPoints()
{
$this->points = user()->points()->sum('total');
}
// points.blade.php livewire component
<div wire:init="loadUserPoints">{{ $points }}</div>
Now let's abstract the answer component.
// answer livewire component (very abstracted)
public function save()
{
user()->answers()->create($this->data);
// this will be listened by the points component
// that will run its query and update your frontend
$this->emit('loadUserPoints');
}
So livewire works mainly for events, you have to use it to pass data cross multiple components. To update your frontend as an SPA you're not gonna use blade components, you have to use livewire component or a lot of javascript to handle the DOM.
I'm basically using VueRouter to create all my routes which is working really well. However, my application is built using Laravel. So if I refresh any of the routes I get an error that the route is not defined. So at the minute in every controller I've had to add an index function. This just returns the view of my app.blade which is just the usual tags etc and the to load my single page app. I'm just wondering if there is a cleaner solution? I guess I could move the return view into a single Controller and make my Controllers extend this. But I'm just wondering if there is a better way I'm missing?
i.e. one of my routes via VueRouter:
{
path: "/clients",
name: "clients",
component: () => import(/* webpackChunkName: "clients" */ "../resources/js/components/Views/Clients/Clients.vue")
},
The route in my clients.php file
Route::get('/clients', [App\Http\Controllers\ClientController::class, 'index'])->name('clients');
Then the ClientController index function
public function index()
{
return view('app');
}
It would just be nice to have the loading of the app.blade done somewhere else and not need to be specified per controller. Any help would be appreciated to ensure it's all done efficiently!
Thanks!
Here is how I solved this issue for one of my projects which is also single page application in Vue and Laravel: https://github.com/lyyka/laravel-vue-blog-spa/blob/master/routes/web.php
Simply, in your routes file, you put this code:
Route::get('/{any}', function () {
return view('welcome');
})->where("any", ".*");
And in my welcome view I have:
#extends('layouts.app')
#section('content')
<div class = "container">
<router-view></router-view>
</div>
#endsection
Basically this will return your app view for any URL and so your Vue SPA should work properly. Generally, it is not a good practice to put callback functions inside your routes file, but in this case, you won't even be using your routes file as it is a SPA, so this solution can pass! :)
You should use your single html file and make a controller.
On your controller
public function index(){
return view('index');
}
on your web.php
basically, you should make the same route on your laravel and vue
Route::get('/products', [ProductsController::class,'index']);
in my vue-routes
import Products from './components/Products.vue'
{
path:'/products'
component: Products
}
How can I redirect to a page when I try to create something that it has to be done in another page?
Example:
I created page that will ask the details for books and saved it to the database. The first page will ask the user to put the cover of the book, title and description. I used Vue Component for the page and axios to save it in the database. I used this code window.location.href = "/create-book/" to redirect to another page which will be the user can start writing and when he saved it, it will save on the current book he was making.
right now Im stuck in this
Vue Component
axios.post('/admin/saveBook', formData).then(function(result){
// console.log(result.data)
window.location.href = "/admin/write-book";
});
and In my controller I used this
Controller
return response()->json($book);
My goal is just to make a one whole page for writing the content of the book. Thanks!
You might look into using Vue Router, specifically Dynamic Route Matching and Programmatic Navigation.
In your router, you'd have a dynamic path for your books.
routes: [
{
// dynamic segments start with a colon
path: '/books/:id',
name: 'book',
component: Book
}
]
Then in your component, you'd navigate to the book on creation.
axios.post('/admin/saveBook', formData).then(function(result) {
this.$router.push({ name: 'book', params: { id: result.data.book.id }});
});
If you need info for the book when you navigate to it, you can either fetch it using the id when mounted or pass the book as a prop on navigation. See Passing Props to Route Components.
I'm not much of a frontend developer but I know enough javascript to do the minimum.
I'm trying to plug into a last piece of login however my vue components are:
"vue-resource": "^0.9.3",
"vue-router": "^0.7.13"
I'm not experienced enough to move up to v1 or v2 respectively.
I would like to achieve something similar to this.
However I'm not getting a successful redirect.
my app.js file:
var router = new VueRouter();
...
import Auth from './services/auth.js';
router.beforeEach(transition => {
if(transition.to.auth &&!Auth.authenticated)
{
transition.redirect('/login');
}
else
{
transition.next();
}
});
```
In my login.js file
```
methods: {
/**
* Login the user
*/
login(e) {
e.preventDefault();
this.form.startProcessing();
var vm = this;
this.$http.post('/api/authenticate',
{ email : this.form.email,
password : this.form.password
})
.then(function(response){
vm.form.finishProcessing();
localStorage.setItem('token', response.data.token);
vm.$dispatch('authenticateUser');
},
function(response) {
if(response.status == 401)
{
let error = {'password': ['Email/Password do not match']};
vm.form.setErrors(error);
}else{
vm.form.setErrors(response.data);
}
});
}
}
I tried to do as suggested:
vm.form.finishProcessing();
localStorage.setItem('token', response.data.token);
vm.$dispatch('authenticateUser');
vm.$route.router.go('/dashboard');
However all it did was append the url on top.
I see that the 3 previous events were successfully done but not the redirect.
it went from:
http://dev.homestead.app:8000/login#!/
to
http://dev.homestead.app:8000/login#!/dashboard
when I need the entire page to go to:
http://dev.homestead.app:8000/login/dashboard#1/
I think i have a missing concept in order to do the redirect correctly.
UPDATE
As per suggested i have added param: append => false but nothing happens.
what i did afterward was within app.js create a method called redirectLogin() with console.log() outputs - that worked. what i did further is i put vm.$route.router.go inside there and called the method via vm.$dispatch('redirectLogin'); and that also didn't work.
NOTE:
The HTML is being rendered in Laravel first. the route I originally had (and working) as login/dashboard and that route is available via normal Laravel route. the blade is being rendered via view template.
So far I've been trying to vue redirect over to login/dashboard (not working) perhaps I should somehow remove login/dashboard and use the route.map and assign login/dashboard?
I would rather keep the login/dashboard as a laravel route due to authentication and other manipulation.
For Vue 2
this.$router.push('/path')
As par the documentation, router.go appends the path in the current route, however in your case it is appending along with # in the router as well.
You can use param: append, to directly arrive at your desired destination, like following:
vm.$route.router.go({name: '/login/dashboard#1/', params: {append: false}})
Edited
If it is not happening, you can try $window.location method like following:
var url = "http://" + $window.location.host + "login/dashboard";
console..log(url);
$window.location.href = url;
I think their is a misunderstanding here of how vue-router works. It seems you are not wanting to load a new route with a corresponding component, rather you simply want to redirect to a new page then let that page load and in turn fire up a fresh instance of vue.
If the above is correct you don't need vue-router at all. Simply add the below when you need to load the page:
window.location.href = '/login/dashboard'
If you'd rather simulate a redirect to that page (no back button history) then:
window.location.replace('/login/dashboard')
EDIT
The above would be fired when you have finished all processing that the page must run to set the users state which the next page requires. This way the next page can grab it and should be able to tell the correct state of the user (logged in).
Therefore you'll want to fire the redirect when the Promise has resolved:
.then(function(response){
vm.form.finishProcessing()
// store the Auth token
localStorage.setItem('token', response.data.token)
// not sure whether this is required as this page, and in turn this instance of vue, is about to be redirected
vm.$dispatch('authenticateUser')
// redirect the user to their dashboard where I assume you'd run this.$dispatch('authenticateUser') again to get their state
window.location.replace('/login/dashboard')
I am opening a form inside one of the pages generated by JeffreyWay's laravel generator.
Except it keeps saying unknown action even though i added the action in the WorkorderController. If I change it to the default actions that was created it worked fine.. like action => 'WorkordersController#create'
Does anyone know how to register a new action using the Route::Resource?
Thanks!
in my form
{{ Form::open(array('action' => 'WorkordersController#time')) }}
in my WorkorderController
public function time()
{
return 'hello world';
}
in my routes
Route::resource('workorders', 'WorkordersController');
The fastest way to resolve this is creating a separate route to your action:
Route::resource('workorders', 'WorkordersController');
Route::post('workorders/time', array('as'=>'workorders.time', 'uses'=>'WorkordersController#time'));
But you also can extend the whole Laravel router system and add new actions.