When I'm submitting the form, I get the following response:
{"data":{"attributes":{"title":null,"description":null},"type":"cards"}}
I'm not sure why I am getting title and description as null.
routes/cards/new.js:
actions: {
save() {
const newCard = this.get('store').createRecord('card', this.get('model'));
newCard.save().then((card) => {
this.transitionTo('cards.all');
});
},
cancel() {
this.transitionTo('cards');
}
}
templates/cards/new.hbs:
<form>
<div>
<label>Title:</label>
{{input type="text" value=model.title}}
</div>
<div>
<label>Body:</label>
{{textarea rows="5" value=model.description}}
</div>
<div>
<button {{action 'save'}}>Speichern</button>
<button {{action 'cancel'}}>Abbrechen</button>
</div>
</form>
Repo link: https://github.com/ghoshnirmalya/hub-client
You are not passing title and description from your .hbs to the route properly. You are creating the model after you fire the action save. Change model.title for title and do the same for the description. Pass them up to your route: {{ save title description }}. Then define two parameters in your save action like: save(title, description). I'm sure you can figure out the rest.
Here is what I usually do in my routes:
setupController(controller /*, model */ ) {
this._super(...arguments);
Ember.set(controller, 'newCard', {}); //newCard is an empty object
},
actions: {
save(newCard) {
Ember.assert('Model is missing or undefined', newCard);
let newCard = this.store.createRecord('card', newCard);
newCard.save().then(( /* response */ ) => {
this.transitionTo('cards.all');
}, (error) => {
//handle error
});
}
}
And in your template you could do something like this:
<form id="save" {{action "save" newCard on="submit"}}>
{{input name="title" id="title" value=newCard.title type="text"}}
<button class="button" type="submit">Save</button>
</form>
Hope this helps. Jeff
In comment you mentioned
doing a console.log(this.get('model')) just prints the model function
That's the answer to your question!. since in route you might have model hook function. so this.get('model') will return function instead of model.
So create controller for cards/new.js and you can move existing save actions. this should work.
Related
I am new to js and would like to convert my JQuery-based js to Vue. I want to send a get request and output back the data. What is the best way of doing this?
Here is the html:
<div>
<div>
<input type="text" id="var1" placeholder="Search...">
</div>
<div>
<button id="submit">Submit</button>
</div>
</div>
<div>
<p>Results</p>
<p id="results"></p>
</div>
Below is my js:
$(document).read(function() {
$('#var1').keypress(function(e) {
if (e.keyCode == 13)
('#submit').click();
});
});
$(document).ready(function() {
$("#submit").click(function() {
var var1 = document.getElementById("var1").value
// sends get request to URL
$.getJSON("URL" + var1, function(search, status) {
console.log(search);
// cont.
$("#results").text(search.results);
});
});
});
EDIT: Here is what I have so far with axios:
function performGetRequest() {
var var1 = document.getElementById('var1').value;
axios.get('URL', {
params: {
id: var1
}
})
.then(function (response) {
console.log(search);
})
}
I am not sure if the above code is correct or how to factor in keypress and click-- is there a simple way to do that?
Well, I am not sure what you want to do with this ajax call, but hopefully this may help you. Vue is data driven, so I always try to focus on that aspect. So this is an example of how you can access and input and send the data using axios.
<div>
<div>
<input v-model='input' type="text" placeholder="Search...">
</div>
<div>
<button #click="searchInput()">Submit</button>
</div>
</div>
<div>
<p>Results</p>
<p >{{ result }}</p>
</div>
you must have those models in your data
// Your data
data() {
return {
input: '',
result: '',
}
}
and your method will look something like this.
searchInput() {
axios({
method: 'GET',
url: url + this.input,
}).then(response => {
this.result = response.data;
}).catch(error => {
//handle error
})
}
So this is a very basic example. you can do the same process in different ways, you could pass the input to the method or loop over the results, but the idea is taking advantage of Vue.js data driven system and think data first.
Hopefully this will help you, remember to escape your input and add necessary validations. Good luck
I am using MEAN JS, i am trying to edit the list items on the list page, but it shows the error as below. i have initiated the data using ng-init="find()" for the list and ng-init="findOne()" for individual data.
Error: [$resource:badcfg] Error in resource configuration for action `get`. Expected response to contain an object but got an array
HTML
Below i the form inside the controller where it initiates the find() and findOne().
<div ng-controller="OrdersController" ng-init="find()">
<div>
<div class="order-filter">
<div ng-repeat="order in orders">
<form ng-init="findOne()" name="orderForm" class="form-horizontal" ng-submit="update(orderForm.$valid)" novalidate>
<input type="text" class="" ng-model="order.title">
<input type="text" class="" ng-model="order.content">
<div class="form-group">
<input type="submit" value="Update" class="btn btn-default">
</div>
</form>
</div>
</div>
</div>
</div>
Controller
$scope.update = function (isValid) {
$scope.error = null;
if (!isValid) {
$scope.$broadcast('show-errors-check-validity', 'orderForm');
return false;
}
var order = $scope.order;
order.$update(function () {
$location.path('orders/' + order._id);
}, function (errorResponse) {
$scope.error = errorResponse.data.message;
});
};
$scope.find = function () {
Orders.query(function loadedOrders(orders) {
orders.forEach(appendFood);
$scope.orders = orders;
});
};
$scope.findOne = function () {
$scope.order = Orders.get({
orderId: $stateParams.orderId
});
};
You need to check your Orders Service which probably is using $resource to provide your API requests (Orders.query)
It should look something like this:
function OrdersService($resource) {
return $resource('api/orders/:orderId', {
orderId: '#_id'
}, {
update: {
method: 'PUT'
}
});
}
The style may be different depending on which version of mean you're using. By default, the $resource query will expect an array of results, but if for some reason you've set "isArray" to false then it will expect an object.
https://docs.angularjs.org/api/ngResource/service/$resource
I've made a registration form with a lot of fields. Since when I submit data and the validator redirects back with errors some inputs are empty and the user has to lose time refilling them, I want to implement some front-end validations.
I'm stuck on checking if an username is already used on submit button press becasuse I'm not expert about AJAX.
In the AuthController I've created a function that returns a Json containing a response in relation of existence or not of the username in the database.
class UserAuthController extends Controller
{
public function isUserNameInUse( $username )
{
if (Auth::where('username', $username) != null){
return [ 'is_used' => 1 ];
}
return [ 'is_used' => 0 ];
}
}
In the routes.php there are these lines:
Route::group([ 'as' => 'api', 'prefix' => 'api', 'namespace' => 'Api'], function () {
Route::group([ 'as' => 'auth', 'prefix' => 'auth'], function () {
Route::any('/is_username_in_use/{username}', [
'as' => 'isUserNameInUse',
'uses' => 'UserAuthController#isUserNameInUse']);
});
});
The view is like that (only a piece of the form):
<form action="{{ route('web.company.postSignup') }}" method="post" id="signup-form" class="form-horizontal">
{!! csrf_field() !!}
#include( 'errors.handler' )
<label for="username">
{{ _('Username*') }} </label>
<input type="text" class="form-control" name="username" id="username"
value="{{ Input::old('username') }}" required>
<label for="password">
{{ _('Password*') }}
</label>
<input type="password" class="form-control" name="password" id="password"
value="{{ Input::old('password') }}" onchange="form.confirmPassword.pattern = this.value;"
required>
<label for="confirmPassword">
{{ _('Confirm Password*') }}
</label>
<input type="password" class="form-control" name="confirmPassword" id="confirmPassword" required>
<button class="btn btn-warning" id="submit-btn" type="submit">{{ _('Sign Up') }}</button>
</form>
This is the script, for now I've only tried to log the response of the controller, but it prints anything.
$(document).ready(function () {
$('form#signup-form').submit(function () {
var input_username = $('input[name=username]').val();
console.log(input_username);
$.getJSON('/api/auth/is_username_in_use/' + input_username, function (json) {
console.log(json);
});
return false;
});
});
There is no need to make an explicit check if user name is in use. You may skip this part and instead, when you storing your user's data validate them accordingly.
An example of this might be
public function store(Request $request)
{
$this->validate($request, [
'username' => 'required|unique:users',
'password' => 'required|confirmed'
]);
// process your logic
}
This way, if validation failed, you'll get a json response object containing error messages.
Note, this will work if you're on Laravel 5. If you are on 4.* refer to documentation for validation part.
You should change return [ 'is_used' => 0 ]; into return Response::json([ 'is_used' => 0 ]); and add use Response; to the top of your controller.
Im working on the tutorial meteor has for my first app. So i wanted to extend it a bit more and have two text boxes, one for comments and one for rating lets say.
The problem is that i cant get correctly the values from both forms (actually cant get the rating value at all) in order to save them in my database and furthermore the enter-submit feature stopped working.
My .js code for body events is:
Template.body.events({
"submit .new-task": function(event) {
// Prevent default browser form submit
event.preventDefault();
// Get value from form element
var text = event.target.text.value;
var rating = event.target.rating.value;
// Insert a task into the collection
Meteor.call("addTask", text, rating);
// Clear form
event.target.text.value = "";
}
});
For add task:
AddTask: function(text, rating) {
//.....
Tasks.insert({
text: text,
createdAt: new Date(),
owner: Meteor.userId(),
username: Meteor.user().username,
rating: rating
});
}
And my HTML:
<form class="new-task">
<h2>What is happening?</h2>
<input type="text" name="text" placeholder="Share your experience!" />
<h2>Rating:</h2>
<input type="text" name="rating" placeholder="insert your rating!" />
</form>
<template name="task">
<li class="{{#if checked}}checked{{/if}}">
{{#if isOwner}}
<button class="delete">×</button>
{{/if}}
<span class="text"><strong>{{username}}</strong> - {{text}}- {{rating}}</span>
</li>
</template>
Your Meteor method addTask is not defined. Call Meteor.call("AddTask", text, rating); instead, or rename your method to addTask.
For example:
if (Meteor.isClient) {
Template.hello.events({
'click button': function () {
Meteor.call("addTask", "1", 2, function(error){
if (error) alert(error.reason);
});
}
});
}
if (Meteor.isServer) {
Meteor.methods({
addTask: function (text, rating) {
check(text, String);
check(rating, Number);
console.log(text);
console.log(rating);
}
});
}
I am fairly new to BackboneJS. After writing multiple GET implementation, I am trying to implement Login screen with Backbone JS.
Folder Structure
app
-->model
-->view
-->templates
-->server
formSignIn.html
<form class="form-signin" role="form">
<h2 class="form-signin-heading">Please sign in</h2>
<input type="email" id="email" class="form-control" placeholder="Email address" required="" autofocus="">
<input type="password" id="password" class="form-control" placeholder="Password" required="">
<label class="checkbox">
<input type="checkbox" value="remember-me"> Remember me
</label>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
Backbone View
var SignInView = Backbone.View.extend({
el:$('.container'),
template:_.template('../templates/formSignIn.html'),
events: {
"click .btn":"signIn"
},
initialize: function() {
this.model.on('change', this.render, this);
},
render: function() {
var attributes = this.model.toJSON();
this.$el.html(this.template(attributes));
},
signIn: function() {
this.model.signIn({
email: $('#email').val(),
password: $('#password').val()
});
}
});
var signInView = new SignInView({model: signInModel});
signInView.render();
Backbone Model
var SignInModel = Backbone.Model.extend({
url:function() {
'http://localhost:3000/singIn'
},
defaults: {
email:"",
password:""
},
parse: function(resp) {
return resp;
},
signIn: function() {
this.save();
}
});
var signInModel = new SignInModel();
Issues:
Template HTML is not rendering. When I open the page it shows ../templates/formSignIn.html. It means _template is not recognizing the html.
How is the view and model implementation? Is this the right way of doing? I am not very confident about calling the model's save().
In answer to your first question _.template(...) takes in a string. If you want the contents of ../templates/formSignIn.html you must include it in the dom or request it, for example using ajax.
If included in the dom it would look something it like this:
// Somewhere in the html...
<script type="text/html" id="form-signin-tpl">
<form class="form-signin" role="form">
...
</form>
</script>
// in your view
_.template($('#form-signin-tpl').html());
If you need to request the template during runtime you can use RequireJS which handles this nicely, or you could manually request it with jQuery, perhaps like this:
$.get( "path/to/templates/formSignIn.html", function( html ) {
var tpl = _.template(html);
});
In answer to the second question
the model's url parameter is a string, not a function.
You only need to define parse if you need to customize how the server's data is parsed.
This is probably more what you're going for:
var SignInModel = Backbone.Model.extend({
url: 'http://localhost:3000/singIn',
defaults: {
email:"",
password:""
},
signIn: function() {
this.save();
}
});
var signInModel = new SignInModel();
Lastly, regarding authenticating a user, a model might not be the best way to handle this. There are a few SO questions regarding athenticating a user in Backbone apps, such as this one