Table not showing the data from database in laravel vue component - javascript

For the past few days, I have been following a tutorial about VUE application from a really good youtuber. I was following each and every step as it was mentioned in the tutorial when suddenly I have come to an abrupt halt. This is because the data from my database is not showing up in the frontend. The database does show that I am storing the data properly, and there are no errors whatsoever.
The video where I got stuck on is: https://youtu.be/bUXhGw4aQtA
Here is the code for the index in my controller
public function index()
{
return User::latest()->paginate(10);
}
Here is the app.js
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
import {
Form,
HasError,
AlertError
} from 'vform'
window.Form = Form;
Vue.component(HasError.name, HasError)
Vue.component(AlertError.name, AlertError)
import VueRouter from 'vue-router'
Vue.use(VueRouter)
let routes = [{
path: '/dashboard',
component: require('./components/Dashboard.vue').default
},
{
path: '/profile',
component: require('./components/Profile.vue').default
},
{
path: '/users',
component: require('./components/Users.vue').default
}
]
const router = new VueRouter({
mode: 'history',
routes // short for `routes: routes`
})
/**
* The following block of code may be used to automatically register your
* Vue components. It will recursively scan this directory for the Vue
* components and automatically register them with their "basename".
*
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
*/
// const files = require.context('./', true, /\.vue$/i);
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default));
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
el: '#app',
router
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<div class="container">
<div class="row mt-5">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Users Table</h3>
<div class="card-tools">
<button class="btn btn-success" data-toggle="modal" data-target="#addNew">Add new <i class="fas fa-user-plus"></i></button>
</div>
</div>
<!-- /.card-header -->
<div class="card-body table-responsive p-0">
<table class="table table-hover">
<tbody>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Type</th>
<th>Registered At</th>
<th>Modify</th>
</tr>
<tr v-for="user in users.data" :key="user.id">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.email}}</td>
<td>{{user.type | upText}}</td>
<td>{{user.created_at | myDate}}</td>
<td>
<a href="#" >
<i class="fa fa-edit blue"></i>
</a>
/
<a href="#">
<i class="fa fa-trash red"></i>
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- /.card -->
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="addNew" tabindex="-1" role="dialog" aria-labelledby="addNewLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addNewLabel">Add Users</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form #submit.prevent="createUser">
<div class="modal-body">
<div class="form-group">
<input v-model="form.name" type="text" name="name"
placeholder="Name"
class="form-control" :class="{ 'is-invalid': form.errors.has('name') }">
<has-error :form="form" field="name"></has-error>
</div>
<div class="form-group">
<input v-model="form.email" type="text" name="email"
placeholder="email"
class="form-control" :class="{ 'is-invalid': form.errors.has('email') }">
<has-error :form="form" field="email"></has-error>
</div>
<div class="form-group">
<textarea v-model="form.bio" type="text" name="bio"
placeholder="Bio"
class="form-control" :class="{ 'is-invalid': form.errors.has('bio') }"></textarea>
<has-error :form="form" field="bio"></has-error>
</div>
<div class="form-group">
<select v-model="form.type" type="text" name="type"
class="form-control" :class="{ 'is-invalid': form.errors.has('type') }">
<option value="">Select user Role</option>
<option value="user">Employee</option>
<option value="manager">Manager</option>
</select>
<has-error :form="form" field="name"></has-error>
</div>
<div class="form-group">
<input v-model="form.password" type="password" name="password"
placeholder="password"
class="form-control" :class="{ 'is-invalid': form.errors.has('password') }">
<has-error :form="form" field="password"></has-error>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Create</button>
</div>
</form>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
users: {},
form: new Form({
name: '',
email: '',
password: '',
type: '',
bio: '',
photo: '',
})
}
},
methods: {
loadUsers() {
axios.get("api/user").then(({
data
}) => (this.user = data));
},
createUser() {
this.form.post('api/user');
}
},
created() {
this.loadUsers();
}
}
</script>
Please let me know if any other code is required for me to elaborate on the query that I have here. I have tried all options that I could think of and search and couldn't get it to work. Hopefully, another set of eyes can help me figure out the problem.
I expect a full table showing all the rows from my database, and the front-end shows nothing. (Note: I did check the network tab in the developer's options in Chrome and there was only a single xhr type and it showed status 200).

I suggest you go on youtube to search for laravel/vue tutorials, there are tons of good resources there that can help you.
For what you are trying to achieve, if you have mounted your component well and can see a dummy test in the component on your browser, then you are half way done.
Inside your mounted hook of your vue component, make an api call to your backend (laravel) to fetch users like so;
axios.get('/get_all_users').then((res)=>{
this.users = res.data
//do a console.log(res.data) to ensure you are getting the users collection
}).catch((err) => {
console.log(err)
});
Inside your data object, create an empty array that holds your users like so;
data(){
return{
users: []
}
}
Now, inside your web.php, create a GET route for this api call;
ROUTE::get('/get_all_users', 'UsersController#FetchUsers');
Note that your controller and method necessarily not be named as above, create a controller, and inside, write a method to fetch users and use them here asap;
Inside your controller, write your method;
public function FetchUsers(){
$users = User::latest()->get();
return response()->json($users, 200);
}
Also note that you will need to import your User model at the top of the controller file like so;
use App\User;
Also ensure before now that you have the User model created that relates to your users table;
By now you should see the arrays of users on your browser developer tool console if everything is fine.
Then in your template, iterate through the users data like so;
<tr v-for="user in users" :key="user.id">
<td>{{ user.id }} </td>
<td>{{ user.name }} </td>
<td>{{ user.email }} </td>
<td>{{ user.created_at }} </td>
</tr>
I will be glad to help in case you need further clarifications.

You need to return your data as json. You can use Laravel [Resource]
(https://laravel.com/docs/5.8/eloquent-resources)
Create user resource
php artisan make:resource User
User Controller
use App\Http\Resources\User as UserResource;
On your Method
$user = User::latest()->paginate(10);
return UserResource::collection($user)

Related

Update data in array not rendering in DOM

On trying to update data in the array from the modal box. The data is not updated in the dom v-for list.
The following consists of modal and details. The data is entered in the modal box which updates the data in details. The cdata is an array which is updated through out the process. When the data is entered in the modal box. This data is pushed in the cdata. Which should update the details v-for loop but it is not happening rather. I tried updating by listening thru events still there's no effects.
data.vue
export default {
props: ["c-data"],
data: function() {
return {};
},
mounted: function() {},
methods: {}
};
<template>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#aModal">Add </button>
<data-detail :cdata="cData"></data-detail>
<add-modal :cdata="cData"></add-modal>
</template>
The following contains code for add modal which updates the data in cData array which is data entered in the data modal.
add-modal.vue
export default {
props: ["c-data"],
data: function() {
return {
cName: "",
cEmail: ""
};
},
mounted() {
console.log(this.cData);
},
methods: {
addC() {
this.cData.push({ cName: this.cName, cEmail: this.cEmail });
console.log(this.cData);
this.$root.$emit("cEvent", this.cData);
}
}
};
<template id="add-modal">
<div class="modal fade" id="aModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-large" role="document">
<div class="modal-content">
<div class="modal-body">
<div class="box">
<div class="row">
<div class="form-group col-sm-6 col-lg-6 col-xl-4">
<div class="input-section">
<input type="text" name="cName" class="form-control" id="c-name" v-model="cName" placeholder="Enter name" value="" required>
<label for="c-name"> Name*</label>
</div>
</div>
<div class="form-group col-sm-6 col-lg-6 col-xl-4">
<div class="input-section">
<input type="text" v-model="cEmail" name="cEmail" class="form-control" id="c-email" placeholder="Enter email" required>
<label for="c-email"> Email*</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-primary" data-dismiss="modal">Close</button>
<button type="button" #click="addC" class="btn btn-primary">Save</button>
</div>
</div>
</div>
</div>
</template>
The follow consists of list of v-for which needs to be updated but are not updating.
export default {
props: ["c-data"],
data: function() {
return {};
},
mounted() {
console.log(this.cData);
},
methods: {}
};
<div v-for="(item, i) in cData" :key="item.id">
{{item.name}}
</div>
I have tried to update it thru listening events but no results as cData was already update in the data component.
You should never directly manipulate data that is passed in as a property.
Using events was the right way to go, you just have to de-couple the newly added data from the properties object.
Use
this.$emit("cEvent", { name: this.cName, email: this.cEmail } );
And listen for it in the parent component
<add-modal :cdata="cData" #cEvent="handleNewData"></add-modal>
...
handleNewData(d) {
this.cData.push(d);
}
Your cData object should only be manipulated directly by the actual owner of that data i.e. the parent where the cData object originates from, not in any component where you pass it in as a property.
Full working example that you can use as a reference: https://codesandbox.io/s/n4lk7rmxx4

Angular 5 Passing form data to another component's dropdown in sync

I have a form (a material dialog modal) which lets the user to create an account, once the user clicks on Register button then the user stays on the same page with the username of that account that he created. The issue I am having is its getting created but its not getting updated in sync with the closing of dialog modal. Means the user should be registered and in parallel that created user value should be populated in the dropdown for better user expereince. I dont want the user to distract from the current page because if the user have entered the details and if that page is reloaded then all the data whatever he entered will be lost. So i dont want that to happen. So for that i created this below code.
<section class="container-fluid with-maxwidth chapter">
<article class="article">
<div class="box box-default">
<div class="box-body">
<mat-horizontal-stepper [linear]="true" #stepper>
<mat-step [stepControl]="firstFormGroup">
<form [formGroup]="firstFormGroup">
<ng-template matStepLabel>Project Registration</ng-template>
<div class="form-group row"></div>
<div class="form-group row">
<label for="name" class="col-md-0 control-label"></label>
<div class="col-md-5">
<mat-input-container class="full-width">
<input required [(ngModel)]="project.name" formControlName="nameCtrl" id="name"
matInput placeholder="Project name">
</mat-input-container>
</div>
</div>
<!-- Repository details -->
<div class="form-group row">
<label for="name" class="col-md-0 control-label"></label>
<div class="col-md-5">
<mat-input-container class="full-width">
<input required [(ngModel)]="project.url" formControlName="urlCtrl" id="repo"
matInput placeholder="Repository URL">
</mat-input-container>
</div>
<div class="col-md-7">
<div class="callout1 text-muted callout-info1">
<p>e.g. https://github.com/username/MyApp.git or
git#github.com:username/MyApp.git.
</p>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-md-0 control-label">
</label>
<div class="col-md-5">
<mat-form-field>
<mat-select placeholder="Repository Credentials" required
[(ngModel)]="project.account.id" formControlName="typeCtrl">
<mat-option *ngFor="let account of accounts" [value]="account.id">
{{account.name}} ({{account.accountType}})
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="col-md-7">
<div class="callout1 text-muted callout-info1">
<p>
Add credentials
<br/>
Credentials are required for automatic test creation and check-in.
</p>
</div>
</div>
</div>
<div>
<mat-card-actions>
<button mat-raised-button color="primary"
class="nav-btn"
[disabled]="firstFormGroup.invalid"
(click)="save(stepper);">Save & Next
</button>
</mat-card-actions>
</div>
<div class="form-group row">
<div class="col-md-0"></div>
<div class="col-md-8">
<button [disabled]="!heroForm.valid" mat-raised-button color="primary" (click)="create();"
class="btn-w-md no-margin-left">Register
</button>
<button mat-button type="button" color="primary" class="btn-w-md" (click)="onClose();">Cancel
</button>
</div>
</div>
</form>
</mat-step>
</mat-horizontal-stepper>
</div>
</div>
</article>
</section>
From the template's below code, here if go to other page and then come to here then the username is adding to the drop down properly. But i dont want the user to go back and forth to see whether his credentials are registered or not but instead i want to show the credentials created on the fly so that he can further move.
<mat-form-field>
<mat-select placeholder="Repository Credentials" required
[(ngModel)]="project.account.id" formControlName="typeCtrl">
<mat-option *ngFor="let account of accounts" [value]="account.id">
{{account.name}} ({{account.accountType}})
</mat-option>
</mat-select>
</mat-form-field>
The code for register dialog box component
export class RegisterComponent implements OnInit{
#Input() entry: Account = new Account();
create(entry: Account) {
this.handler.activateLoader();
this.snackbarService.openSnackBar(this.entry.name + " registering...", "");
this.accountService.create(entry).subscribe(results => {
this.entry = entry;
this.handler.hideLoader();
if (this.handler.handle(results)) {
return;
}
this.snackbarService.openSnackBar(this.entry.name + " registered successfully", "");
this.onClose();
// this.router.navigateByUrl('/app/projects', {skipLocationChange: true}).then(()=>
// this.router.navigate(['/app/projects/new']));
this.router.navigate(['/app/projects/new']);
}, error => {
this.handler.hideLoader();
this.handler.error(error);
});
}
onClose(){
this.dialogRef.close();
}
}
This is where i have written the service:
import { Account } from './../models/project.model';
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '#angular/common/http';
import { Headers } from '#angular/http';
import { Observable, Subject } from 'rxjs';
import 'rxjs/add/observable/timer';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class AccountService {
private serviceUrl = '/api/v1/accounts';
private entry = new Subject<Object>();
entry$ = this.entry.asObservable();
constructor(private http: HttpClient) {
}
create(entry: Account): Observable<any> {
return this.http.post(this.serviceUrl, entry);
}
emitAccount(entry){
this.entry.next();
}
}
I want the user to be on the same page and should update the dropdown with latest results. How is that possible? Could you please suggest me? What i have done wrong with my code.
Thanks.
create Service:
let newEntry = this.http.post(this.serviceUrl, entry);
emitAccount(newEntry);
return newEntry;
Register Component:
entry$.subscribe(updateAccount => {
accounts.push(updateAccount)
}
So to check .. it's about this section?
<mat-option *ngFor="let account of accounts" [value]="account.id">
{{account.name}} ({{account.accountType}})
</mat-option>
BEcause I don't see anything in your code repopulating accounts array after registering.
I can't see where you bind the accounts array.

Vue.js same form for add and edit

I'm a rookie on vue.js and I'm trying to extend some tutorials a completed.
Been fighting with this three hours now and I'm frustrated. FYI, I'm using firebase but I'm not sure it really matters here.
So, I have a CRUD app for listing movies (I told you it was basic!).
There is a form at the top of the page where you can add movies, and a table below it, where the new registries are listed. This works well.
I added Edit and Delete buttons to each row on the table. The delete function works. But the Edit function is the problem.
I'd like to use v-if on the initial form, to trigger different methods (save, edit) and show different buttons (Add, Save, Cancel).
I'm not sure how to access the objects to do this, I tried a couple of things and the v-if says the object is not defined.
thank you for reading, please ask anything you need.
import './firebase' // this has my credententials and initializeApp
import Vue from 'vue'
import App from './App'
import VueFire from 'vuefire'
Vue.use(VueFire)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
template: '<App/>',
components: { App }
})
<template>
<div id="app" class="container">
<div class="page-header">
<h1>Vue Movies</h1>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3>Add Movie</h3>
</div>
<div class="panel-body">
<div v-if="!isEditing">
<form id="form" class="form-inline" v-on:submit.prevent="addMovie">
<div class="form-group">
<label for="movieTitle">Title:</label>
<input type="text" id="movieTitle" class="form-control" v-model="newMovie.title">
</div>
<div class="form-group">
<label for="movieDirector">Director:</label>
<input type="text" id="movieDirector" class="form-control" v-model="newMovie.director">
</div>
<div class="form-group">
<label for="movieUrl">URL:</label>
<input type="text" id="movieUrl" class="form-control" v-model="newMovie.url">
</div>
<input type="submit" class="btn btn-primary" value="Add Movie">
</form>
</div>
<div v-else>
<form id="form" class="form-inline" v-on:submit.prevent="saveEdit(movie)">
<div class="form-group">
<label for="movieTitle">Title:</label>
<input type="text" id="movieTitle" class="form-control" v-model="movie.title">
</div>
<div class="form-group">
<label for="movieDirector">Director:</label>
<input type="text" id="movieDirector" class="form-control" v-model="movie.director">
</div>
<div class="form-group">
<label for="movieUrl">URL:</label>
<input type="text" id="movieUrl" class="form-control" v-model="movie.url">
</div>
<input type="submit" class="btn btn-primary" value="Save">
<button v-on:click="cancelEdit(movie['.key'])">Cancel</button>
</form>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3>Movies List</h3>
</div>
<div class="panel-body">
<table class="table table-stripped">
<thead>
<tr>
<th>Title</th>
<th>director</th>
</tr>
</thead>
<tbody>
<tr v-for="movie in movies">
<td>
<a v-bind:href="movie.url" v-bind:key="movie['.key']" target="_blank">{{movie.title}}</a>
</td>
<td>
{{movie.director}}
</td>
<td>
<button v-on:click="editMovie(movie)">Edit</button>
</td>
<td>
<button v-on:click="removeMovie(movie)">Remove</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script>
import { moviesRef } from './firebase'
export default {
name: 'app',
firebase: {
movies: moviesRef
},
data () {
return {
isEditing: false, // maybe this helps?
newMovie: {
title: '',
director: '',
url: 'http://',
edit: false // or maybe this??
}
}
},
methods: {
addMovie: function() {
moviesRef.push( this.newMovie )
this.newMovie.title = '',
this.newMovie.director = '',
this.newMovie.url = 'http://'
this.newMovie.edit = false
},
editMovie: function (movie){
moviesRef.child(movie['.key']).update({ edit:true }); // can't access this one with v-if, not sure why
//this.newMovie = movie;
},
removeMovie: function (movie) {
moviesRef.child(movie['.key']).remove()
},
cancelEdit(key){
moviesRef.child(key).update({ edit:false })
},
saveEdit(movie){
const key = movie['key'];
moviesRef.child(key).set({
title : movie.title,
director : movie.director,
url : movie.url,
edit : movie.edit
})
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
You should change the isEditing to true when the Edit button clicked, and you should define the data movie.
editMovie: function (movie){
...
this.movie = Vue.util.extend({}, movie); // deep clone to prevent modify the original object
this.isEditing = true;
},
As suggested in the comments (by Ben), I added the movie declaration to the initial data object. So now it looks like this:
data () {
return {
isEditing: false,
newMovie: {
title: '',
director: '',
url: 'http://',
edit: false
},
movie: {
edit: false
}
}
},
Now v-if works just fine, like this:
<div v-if="!movie.edit">
"is Editing" was no longer necessary so I removed it.

How to reference a global function in a Vue component?

I have a Vue component that has a 'select state' dropdown element. I want to add a js function that populates the options with the 50 states instead of having to hard code them. I will also have this dropdown in a couple other places so I want this function to be accessed from outside the component. What is the best way to accomplish this?
<template>
<div class="section" v-bind:class="sectionClass" data-mh="group3">
<h3>{{sectionTitle}}</h3>
<div class="section-content display-area">
<i class="icon icon-health img-left"></i>
<form>
<div class="row mt">
<div class="col-xs-12 col-sm-8">
<div class="same-height-parent">
<div class="same-height">
<input type="text" class="form-control" placeholder="Enter Name">
</div>
<div class="same-height">
<select name="state" id="state" class="form-control" tabindex="9">
<option value="">- Select State -</option>
</select>
</div>
</div>
<!-- same-height-parent -->
</div>
<div class="col-xs-12 col-sm-4">
<button type="submit" class="btn btn-success btn-block btn-fz20">Search</button>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
export default {
name: 'nameSearch',
data: function() {
return {
sectionTitle: 'Name Search'=
}
}
}
</script>
you may want to export the function from some other file, this is simply a case of declaring it the way you want.
in some other file...
// utils.js
export function createOptions (someArg) {
let options = [ ... ]
return options
}
in your .vue file
<script>
import { createOptions } from './utils'
export default {
...
data () {
return {
options: createOptions()
}
}
}
</script>
You may also want to try snovakovic's advice to externalise the dropdown component instead, whatever brings you more flexibility
Why not just create states components that handles drop-down and then include that component everywhere where it's used.
If you want just a function then create js file that expose that function and than import that file inside component.

Ember app not posting to server with Ember Data

I am trying to connect my ember app to a node server on the backend. Right now, I have a sign up and login form and when the user submits either form it will go through an authentication process setup in node using Passport. However when the submit button is pressed it just reloads the current page and doesn't even send a HTTP post request. Any ideas on why this is happening/ how to fix it?
Here is my adapter:
import DS from "ember-data";
var ApplicationAdapter = DS.RESTAdapter.extend({
host: 'http://localhost:8080'
});
export default ApplicationAdapter;
Here is my sign up controller:
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
new: function() {
console.log('creating new user...');
var model = this.get('user');
user = this.get('store').createRecord('user', {
title: model.get('title'),
password: model.get('password')
});
user.save().then(function(data) {
// Clear the form.
Ember.$(':input').val('');
});
},
}
});
Here is my model:
import DS from 'ember-data';
export default DS.Model.extend({
username: DS.attr('string'),
password: DS.attr('string')
});
Here is the form:
<div class="row text-center">
<h1>Signup</h1>
</div>
<form>
<div class="row">
<div class="medium-6 medium-centered columns">
{{input value=username type="text" placeholder="Username"}}
</div>
</div>
<div class="row">
<div class="medium-6 medium-centered columns">
{{input value=password type="password" placeholder="Password"}}
</div>
</div>
<div class="row">
<div class="medium-6 medium-centered columns">
{{input class="button" type="submit" value="Signup"}}
</div>
</div>
</form>
Alright, so there seems to be a few issues here.
First, looking at the controller that you posted, there are a few things that don't look right:
The user variable is never declared
You try to get the user property from the controller, but it is never defined
You try to clear the form using Ember.$(':input').val(''); which doesn't really make any sense, if the inputs are bound to the template.
We'll start by cleaning up the template, which will drive the improvements to the controller:
<div class="row text-center">
<h1>Signup</h1>
</div>
<form>
<div class="row">
<div class="medium-6 medium-centered columns">
{{input value=username type="text" placeholder="Username"}}
</div>
</div>
<div class="row">
<div class="medium-6 medium-centered columns">
{{input value=password type="password" placeholder="Password"}}
</div>
</div>
<div class="row">
<div class="medium-6 medium-centered columns">
<button class="button" type="submit" {{action 'createUser'}}>Signup</button>
</div>
</div>
</form>
The major issues seems to be that you're using an {{input}} helper for the button, which doesn't really make any sense. The {{input}} helper if for inputting text. We've also moved the action to be bound to the button being clicked instead, which is the behavior that you want.
Now, the controller:
import Ember from 'ember';
export default Ember.Controller.extend({
// Username for the new user
username: '',
// Password for the new user
password: '',
actions: {
// Create a new user
createUser() {
const username = this.get('username');
const password = this.get('password');
this.get('store').createRecord('user', {
username,
password
}).save()
.then(() => {
this.send('clearForm'); // Invokes the `clearForm` action on the controller
})
.catch(() => {
// Do some kind of error handling if the creation fails
});
},
// Clear the form
clearForm() {
this.set('username', '');
this.set('password', '');
}
}
});
Now we have a controller with two properties defined, to hold the username and password for the new user. They are bound to the input fields in the template, and we manipulate them both get the values out of the template and also to clear them again.
You have a submit button that does a post request by default. You can do the following.
<form {{action 'new' on='submit'}}>
<div class="row">
<div class="medium-6 medium-centered columns">
{{input value=user.username type="text" placeholder="Username"}}
</div>
</div>
<div class="row">
<div class="medium-6 medium-centered columns">
{{input value=user.password type="password" placeholder="Password"}}
</div>
</div>
<div class="row">
<div class="medium-6 medium-centered columns">
<button class="button" type="submit">Signup</button>
</div>
</div>
</form>
This basically says intercept the submit event and call the action instead.
Note that I also added user. to your input values, otherwise you'd get them from your controller as this.get('username'), etc.

Categories