I'm following along with Ryan Bates backbone.js RailsCast, part II. In it, he's making a raffle application where you can add new names to a list and then pick a random winner. This is the form he uses in the template to submit the new name. However, when I press submit, nothing happens. It doesn't click.
<h1>raffler</h1>
<form id="new_entry">
<input type="text" name="name" id="new_entry_name">
<input type="submit" value="Add">
</form>
<ul>
<% for entry in #entries.models: %>
<li><%= entry.get('name') %></li>
<% end %>
</ul>
In the view, on the submit event he uses the createEntry function to create a new name
events:
'submit #new_entry': 'createEntry'
initialize: ->
#collection.on('reset', #render, this)
render: ->
$(#el).html(#template(entries: #collection))
this
createEntry: (event) ->
event.preventDefault()
#collection.create name: $('#new_entry_name').val()
Any ideas what might be wrong?
Related
The following code allows user's to check a box to include an amenity on a post using MongodB/Node/Express. It is working perfectly to let users select their amenities and then shows those selections as icons.
However I am unable to EDIT these posts in my edit route . That is the problem. See code at bottom. How would I change my code to be able to edit the icons?
// Simplified Schema
var rentalsSchema = new mongoose.Schema({
amenities: Array
});
// User Checks their amenities
<input type="checkbox" name="amenities" value="wifi"><span>Wi-fi</span>
<input type="checkbox" name="amenities" value="tv"><span>TV</span>
// This code loops through the array and shows the relevant icons using Google's material icons.
<div class="list-group">
<li class="list-group-item active">Amenities</li>
<li id="amenitiesBox" class="list-group-item">
<% for(var i=0; i<rentals.amenities.length; i++){ %>
<i class="material-icons"><%=rentals.amenities[i]%></i>
<% } %>
</li>
</li>
</div>
</div>
// The problem is here in my edit route. Simplified below
<form id='rentalEdit' action="/rentals/<%=rentals._id %>/?_method=PUT" method ="POST">
<input Checked type="checkbox" name="rentals[amenities]" value="wifi"><span>Wifi</span>
</form>
Ah got it!
In my router.put I added:
var amenities = req.body.amenities; & amenities: amenities.
Then I just added my amenities to the edit form in this format.
<input name="amenities" type="checkbox" value="wifi" <%= rentals.amenities.indexOf("wifi") !== -1 ? "checked" : "" %> >wifi
I am creating a project to put into practice what I have learned about AngularJS. I created a form, which uses a controller. In the form, I have a button to save the information filled in by the user. After the information is save into the database I would like to call a second form to continue, (this form has its own controller) etc. How can I do that ?
If you're not navigating to a different view, you probably dont need another controller. You can show and hide forms conditionally with ng-if. Ie. say first form is done, you've posted it to the database. You can do something like this
$scope.form = 1
<form id="form1" ng-if="form === 1">
//your form html
</form>
<form id="form2" ng-if="form === 2">
//your form html
</form>
then when form1 is submitted, you can do
$scope.form = 2
in your controller to hide the first form and render the second one
If you're set on the different forms having different controllers, you can do something like this
<div controller="mainCtrl">
<form controller="form1Ctrl" id="form1" ng-if="form === 1">
//your form html
</form>
<form controller="form2Ctrl" id="form2" ng-if="form === 2">
//your form html
</form>
</div>
You would set the form variable from the mainCtrl's scope
You can use ng-submit for this:
<form ng-submit="goToNextForm()">
<input type="text" ng-model="email">
<button type="submit" value="submit">
</form>
And in controller:
$scope.goToNextForm = function(){
//code to save data and move to next controller/form here
}
In the simple Angular app I'm working on there is a parent form with various child forms that are created from an ng-repeat. I'd like a submit button to be tied to the parent form's $valid property OR some other simple way to enable the submit button when the form is what I consider to be valid. However, due to the user workflow a new child form is added after the fields of the last child form are completed. Thus, even a perfect form's last row is always empty & thus invalid (as there are required fields). Any suggestions on how to handle enable/disable of a submit button in this situation? I've created a fiddle that shows the issue. There is a submit button linked to the parent form's $valid, which does not show up unless the last form (row) is valid. Then there's a second submit button, whose enabled property I control by explicitly looking at all child forms and setting a scope variable to true or false based on my requirements. I think this solution is inelegant and there's got to be a better way.
https://jsfiddle.net/godinger/r5yx5z4b/
Here's the HTML form:
<div ng-app="myApp" ng-controller="myCtrl">
<pre>Parent Form Valid: {{parentForm.$valid}}</pre>
<ng-form name="parentForm">
<div ng-repeat="person in people">
<ng-form name="childForm" novalidate>
<input name="firstName"
required
ng-model="person.firstName"
ng-init="person.form=childForm"/>
<input name="lastName"
required
ng-model="person.lastName"
ng-init="person.form=childForm"/>
<span>Valid: {{childForm.$valid}}</span>
</ng-form>
</div>
<button ng-submit ng-disabled="parentForm.$invalid">
Submit
</button>
<button ng-submit ng-disabled="!enableSubmit">
Workaround Submit
</button>
</ng-form>
</div>
And here's the Angular code:
var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", function($scope) {
$scope.enableSubmit = false;
$scope.people = [
{firstName: 'John', lastName: "Adams"},
{firstName: 'Alex', lastName: 'Hamilton'},
{firstName: '', lastName:''}];
$scope.$watch(updateSubmit);
function updateSubmit(){
if (!$scope.people){
$scope.enableSubmit = false;
return;
}
var numberOfPeople = $scope.people.length;
for (var i=0; i<numberOfPeople-1; i++){
var personForm = $scope.people[i].form;
if (personForm.$invalid){
$scope.enableSubmit = false;
return;
}
}
var lastPerson = $scope.people[numberOfPeople-1];
var lastPersonForm = lastPerson.form;
if (lastPersonForm.$valid){
$scope.enableSubmit = true;
return;
}
if (lastPerson.firstName || lastPerson.lastName){
$scope.enableSubmit = false;
return;
}else{
$scope.enableSubmit = true;
return;
}
}
});
I'm not sure that your implementation makes the most sense, but if want you want to do is provide "different html" based on the last element in ng-repeat, the simplest way is to use the $last element local variable. There are a number of ways to do this...but here is the simplest answer to your question:
<ng-form ng-if="!$last" name="childForm" novalidate>
<input name="firstName" placeholder="First name"
ng-model="person.firstName"
ng-init="person.form=childForm"/>
<input name="lastName"
required placeholder="First name"
ng-model="person.lastName"
ng-init="person.form=childForm"/>
<span>Valid: {{childForm.$valid}}</span>
</ng-form>
<div ng-if="$last">
Do Other Logic / Show other stuff (this could even be repeat all the form elements again, but remove all of the 'required' properties)
</div>
I have a form inside a modal pop up. I am trying to run form validation on the inputs after the user attempts to submit the form. So far, I'm struggling to make things work.
In my view, I have the following (sorry if there are any syntax errors, I'm converting this from jade on the fly):
<script type="text/ng-template", id="modalVideoNew">
<div class="ngdialog-message">
<form class="form-horizontal" ng-submit="submitForm()" novalidate name="newVideoForm">
...
<div class="form-group">
<label> Title </label>
<div class="col-sm-8">
<input type="text" name="title", required='', ng-model="newVideoForm.title">
<span class="text-danger" ng-show="validateInput('newVideoForm.title', 'required')"> This field is required</span>
</div>
</div>
</div>
</script>
And then in my controller, where I'm calling the ng-dialog pop up, I have this:
$scope.newVideo = function() {
ngDialog.openConfirm({
template: 'modalVideoNew',
className: 'ngdialog-theme-default',
scope: $scope
}).then(function() {
$scope.validateInput = function(name, type) {
var input = $scope.newVideoForm[name];
return (input.$dirty || $scope.submitted) && input.$error[type];
};
var newVideo = $scope.newVideoForm;
...
Right now, I am still able to submit the form, but once I open it back up I see the 'This field is required' error message. Also, the input is pre-filled with [object, Object] instead of an empty text input box.
A way of cleaning your model would work with using a model var that belongs to your parent controller and cleaning it in the callback. Check out how the template has attached your parent controller's var FormData.
Check this out
So about your validation, what I would recommend you is to have your own controller in it, no matter how much code it will have. It helps you keeping concepts of modularization and a better control over your scopes. This way will also facilitate a lot when validating.
I'm building a form and within that form is a secondary function that I wish to run. However, when I click the button for my secondary function, backbone fires and runs validation over the whole form. How do I either:
a) Make Backbone ignore that specific button and do nothing when it's clicked
or
b) (Preferred) Tie Backbone validation to only the form submit button or the button type "submit".
Example:
<form name="myForm" >
<input type="text" name="yourName" ng-model="yourName" required />
<input type="text" name="postcode" ng-model="postcode" required />
<button id="checkPostcode" type="button" >Check Postcode</button>
<button id="submit" type="submit" >Submit</button>
</form>
In this case, I only wish Backbone to run validation when the submit button is pressed, so that I can run my checkPostcode function without interference.
Thanks :)
You should add an eventListener to the button and prevent the default. Something like this:
var view = Backbone.View.extend({
events: {
"click #checkPostcode": "checkPostcode"
},
checkPostcode: function(event) {
event.preventDefault();
// the actual check would go here
}
});