I'mn creating a multi step form wizard (using Twitter Bootstrap Wizard) and looking at the Parsley multi step example I'm not sure how I would implement it if I have more then two steps my current form has at least 4 steps.
This is what I don't understand
<span class="next btn btn-info pull-right" data-current-block="1" data-next-block="2">Next ></span>
My next button is constant
Here is the parsley example
<form id="demo-form" data-parsley-validate>
<div class="first block1 show">
<label for="firstname">Firstname:</label>
<input type="text" name="firstname" data-parsley-group="block1" required/>
<label for="lastname">Lastname:</label>
<input type="text" name="lastname" data-parsley-group="block1" required />
<span class="next btn btn-info pull-right" data-current-block="1" data-next-block="2">Next ></span>
</div>
<div class="second block2 hidden">
<label for="fullname">Email:</label>
<input type="text" name="fullname" required data-parsley-type="email" data-parsley-group="block2" />
<span class="next btn btn-info pull-left" data-current-block="2" data-next-block="1">< Previous</span>
<input type="submit" class="btn btn-default pull-right" />
</div>
</form>
<script type="text/javascript">
$(document).ready(function () {
$('.next').on('click', function () {
var current = $(this).data('currentBlock'),
next = $(this).data('nextBlock');
// only validate going forward. If current group is invalid, do not go further
// .parsley().validate() returns validation result AND show errors
if (next > current)
if (false === $('#demo-form').parsley().validate('block' + current))
return;
// validation was ok. We can go on next step.
$('.block' + current)
.removeClass('show')
.addClass('hidden');
$('.block' + next)
.removeClass('hidden')
.addClass('show');
});
});
</script>
The solution or workaround is pretty simple. It's best just to use Bootstrap Wizard methods your going to want to have the following
$('#w4').bootstrapWizard({
tabClass: 'wizard-steps',
nextSelector: 'ul.pager li.next',
previousSelector: 'ul.pager li.previous',
firstSelector: null,
lastSelector: null,
onNext: function( tab, navigation, index, newindex ) {
var current = index,
next = current + 1;
// only validate going forward. If current group is invalid, do not go further
// .parsley().validate() returns validation result AND show errors
if (next > current)
if (false === $('#bioForm').parsley().validate('step' + current))
return false;
// validation was ok. We can go on next step.
$('.step' + current)
.removeClass('show')
.addClass('hidden');
$('.step' + next)
.removeClass('hidden')
.addClass('show');
}
});
I know this is late, but could help someone else in need .Had similar problem and this is how i solved it.
i added this to each control i need to validate on each steps
add this to step1 controls : data-parsley-group="block-1"
add this to step2 controls: data-parsley-group="block-2"
....keep increasing for each steps.
in your bootstrapwizard javascript add the code below in the 'OnNext' fuction.
$('#form').bootstrapWizard({
tabClass: 'wizard-steps',
'onNext': function (tab, navigation, index) {
var $valid = $("#form").parsley().validate({ group: 'block-' + index });
if(!$valid) {
return false;
}
}
});
Hope this helps you out.
Related
I am using this template and binding data with it
<div id="groupSegment" data-ng-repeat="q in CurrentQuestion">
Segment Info
<div>{{q.SegmentName}}</div>
Questions:
<div>{{q.Title}}</div><div>{{q.Description}}</div>
<input type="button" value="Previous" id="d{{q.PrevQuestIndex}}" data-ng-click="ChangeQuestion({{q.PrevQuestIndex}})" /><br /> <input id="d{{q.NextQuestIndex}}" type="button" value="Next" data-ng-click="ChangeQuestion({{q.NextQuestIndex}})" />
</div>
Issue coming that on click of Next and Previous its not updating the value of index when clicking next time.
Html shows that the updated value is there but when i am clicking then its showing the value that was set when html renderd
Here is the funtion that firing on click.
$scope.ChangeQuestion = function (index) {//this indux value not getting changed
if (index < 0 || index > $scope.Questions.length)
return;
$scope.CurrentQuestion = [];
var i = 0;
$($scope.Questions[index]).each(function () {
if (i == 0) {
$scope.CurrentQuestion.push({ Title: this.Title, Description: this.Description,SegmentName: this.SegmentName, NextQuestIndex: index + 1, PrevQuestIndex: index - 1 });
}
i++
});
$scope.$apply();
};
So how I can refresh this on click parameter
Normally I'm using ng-click instead of data-ng-click which you used..
Also You don't need to pass parameters with {{}} if you use it inside ng- tag.
Change it as ng-click="ChangeQuestion(q.PrevQuestIndex)"
<div id="groupSegment" data-ng-repeat="q in CurrentQuestion">
Segment Info
<div>{{q.SegmentName}}</div>
Questions:
<div>{{q.Title}}</div><div>{{q.Description}}</div>
<input type="button" value="Previous" id="d{{q.PrevQuestIndex}}" ng-click="ChangeQuestion(q.PrevQuestIndex)" /><br />
<input id="d{{q.NextQuestIndex}}" type="button" value="Next" ng-click="ChangeQuestion(q.NextQuestIndex)" />
</div>
I’m using a library called floating-tabs.js which is being used to create floating navigational buttons: here’s an example of what the layout looks like
<floating-tabs>
//this is my button
<floating-tabs-item icon="ion-android-arrow-dropright-circle" click="goNext(data)"></floating-tabs-item>
</floating-tabs>
<ion-content>
<form name=“formName” ng-submit="goNext(data)">
***form stuff
</form>
</ion-content>
How can I submit/validate the form without having my button inside the form tags
Thanks guys
here i am using simple change password form.
<form name="changepasswordform" novalidate>
<input type="password" placeholder="New Password" class="reset-inputs" name="newpassword" ng-keyup="compare()" ng-model="changePassword.newpassword" maxlength="10" required/>
<span style="color:red" ng-show="submitted && changepasswordform.newpassword.$error.required">Required</span>
</form>
<button type="button" class="reset-submit" ng-click="changepassword(changepasswordform.$valid,changePassword)">Change Password</button>
it consist button out side the form
and please use the script in your controller
$scope.submitted = false;
$scope.changepassword = function(formValidStatus, formdata) {
if (!formValidStatus) {
$scope.submitted = true;
} else {
$scope.submitted = false;
}
}
in the script i am checking form is valid or not if form is not valid i am showing error messages by using submitted variable from script.
This works for me
I have the following div to allow a user to upload multiple file inputs:
<div class="form-inline" ng-repeat="file in selectedFiles track by $index">
<input class="form-control" style="width:350px;" type="text" name="description{{$index}}" ng-model="file.fileDescription" ng-disabled="isDisabled" />
<input class="form-control" style="width:350px;" type="file" name="file_file{{$index}}" ng-model="file.file" accept="application/pdf" ng-disabled="isDisabled" />
<button ng-if="$last" class="btn btn-link" ng-click="addFile();" ng-disabled="isDisabled"><i class="glyphicon glyphicon-plus-sign text-success large-font"></i></button>
<button class="btn btn-link" ng-click="removeFile($index);" ng-disabled="isDisabled"><i class="glyphicon glyphicon-remove text-danger large-font"></i></button>
</div>
And I have the following in my scope:
scope.selectedFiles = [];
scope.addFile = function() {
scope.selectedFiles.push({});
};
scope.removeFile = function(index) {
if(index >= 0) {
scope.selectedFiles.splice(index, 1);
}
};
If I press the addFile button, it adds rows just fine. If I press the removeFile button, a line is removed, however, the file inputs still remain the same.
For example, if I press the addFile button 3 times and put in 3 files. It has all 3 lines as it should. If I then press the removeFile button on the first or second line, the second line is correct on the left, but the 3rd file input was removed, not either of the first two.
How can I get this to remove lines as I would expect it to?
I'm not sure of why it behave weird on you. It works just fine on this fiddle I made so please double check :)
I intentionally removed the track by and added examples to the code to show that it removes the one you clicked:
$scope.selectedFiles = [
{file:'File1', fileDescription: 'First file'},
{file: 'File2', fileDescription: 'Second file'},
{file: 'File3', fileDescription: 'Third file'}
];
$scope.addFile = function() {
$scope.selectedFiles.push({});
};
$scope.removeFile = function(index) {
if(index >= 0) {
$scope.selectedFiles.splice(index, 1);
}
};
Maybe try:
delete scope.selectedFiles[index];
I have searched thoroughly everywhere and can't seem to find the solution to my problem.
I am trying to make a form to fill in to create new task object onto projects on the website like a scrum backlog or something in Angular and angular-ui.
I use Angular-UI for typeahead functionality for when adding team members to a task, so available members on a project pop-up. I have seen guys with similar problems, but nothing seems to solve it for me. Below is the HTML and the controller. Sorry for the long markup, but I suspect it has to do something with nesting the controllers and mixing the scopes, so I'm including everything relevant.
<div ng-controller="SubmitCreateTaskController">
<div class="modal fade" id="taskModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span>
<span class="sr-only">Close</span>
</button>
<h4 class="modal-title" id="myModalLabel">New Task</h4>
</div>
<div class="modal-body">
<form role="form" method="post" name="create-task">
<div class="form-group">
<label for="taskname">Task Name</label>
<input type="text" class="form-control" id="taskname" ng-model="taskForm.taskName" placeholder="Task Name">
</div>
<div class="form-group">
<label for="taskdesc">Description</label>
<textarea class="form-control" id="taskdesc" size="3" ng-model="taskForm.taskDescription" placeholder="Enter a short description here..." rows="2"></textarea>
</div>
<div class="form-group">
<label for="assigneddate">Assigned Date</label>
<input type="text" class="form-control" id="assigneddate" ng-model="taskForm.assignedDate">
</div>
<div ng-controller="TypeAheadController">
<div class="form-group">
<label for="contributors">Add Contributors</label>
<input id="contributors" type="text" class="form-control" ng-model="contrib.selected" typeahead="member for member in contrib.stream_members | filter:$viewValue"
typeahead-editable="false" typeahead-on-select="contrib.onSelect($item)">
</div>
<div class="form-group">
<label for="users">Contributors:</label>
<textarea class="form-control" disabled="disabled" id="users" ng-model="contrib.entered" rows="1"></textarea>
</div>
</div>
<div class="form-group">
<label for="taskcomments">Comments</label>
<textarea class="form-control" id="taskcomments" ng-model="taskForm.comment" placeholder="Comments" rows="2"></textarea>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" ng-click="taskForm.submit()">Add Task</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
</div>
</form>
</div>
</div>
</div>
</div>
Controllers:
.controller('SubmitCreateTaskController', ['$scope', '$http', function($scope, $http) {
$scope.taskForm = {};
$scope.taskForm.taskName = '';
$scope.taskForm.taskDescription = '';
$scope.taskForm.assignedDate = new Date();
$scope.taskForm.contributors = [];
$scope.taskForm.comment = '';
$scope.taskForm.submit = function(item, event) {
var formData = {name: $scope.taskForm.taskName,
description: $scope.taskForm.taskDescription,
status: 'open',
assigned: $scope.taskForm.assignedDate,
completed: null,
contributors: $scope.taskForm.contributors,
comments: [{body: $scope.taskForm.comment,
user: 'RACHE User',
date: new Date()
}]
};
var postURL = '../create_task/' + $scope.stream_name;
$http.post(postURL, formData)
.success(function(){
taskForm = {}; // empty the form of previous input values
alert('New Task Created for ' + $scope.stream_name);
})
.error(function(res) {
alert(res.data);
});
};
}])
.controller('TypeAheadController', ['$scope', '$http', function($scope, $http) {
$scope.contrib = {};
$scope.contrib.selected = '';
$scope.contrib.stream_members = undefined;
$scope.contrib.entered = [];
$http.get('/stream_members/' + $scope.stream_name)
.then(function(res) {
$scope.contrib.stream_members = res.data.stream_members;
});
$scope.contrib.onSelect = function($item) {
$scope.contrib.selected = '';
$scope.contrib.entered.push($item);
console.log($scope.contrib.entered);
};
This last bit is the important part in 'TypeAheadController'. I am trying to add the poped-up team members to a textarea just below which would be sent to the DB later. That is why I have bound the actual typeahead input box to 'contrib.select' and the "display/post" box to 'contrib.entered', so the search can be continued after adding one member, the search box is cleared, selected member is added to box below, new search can begin. In the mark up I call the last (onSelect) function in the typeahead-on-select callback. This so that I can clear the input box and another member can be easily added without deleting manually. IN this function the entered member should be appended to the array that is bound to below "display/post" box. This happens, since the console log shows good value, the search/input field gets cleared, so the function gets called as well.
The view does not get updated with the updated array bound to display box however. I have tried EVERYTHING. I have googled around and found it here that dot notation needs to be used as Angular can't update with primitives, but this hasn't helped either.
Everything works fine, the logic is good, values are good when I print them out, pop-up works and clears up as expected, but The damn textarea under it does not get updated.
Any suggestions? I have been stuck on this for almost a day now and I am really frustrated by this. I would be ever so greatfull for any help!
Thanks guys in advance!
Textarea do use the value attribute, your code isn't working because contrib. entered isn't between the tags, but because you can not bind the textarea to an array (it needs to bind to a string).
look at this plunker, if you do this in your html:
<textarea class="form-control" disabled="disabled" id="users" rows="1" ng-model="contrib.enteredString"></textarea>
and add this line at the end of your typeahead controller:
$scope.contrib.enteredString = $scope.contrib.entered.toString();
then the text area will update
Textareas don't use the ng-value as their value is contained within the tag. Remove the ng-model and put the value between the tags.
<textarea class="form-control" disabled="disabled" id="users" rows="1">{{contrib.entered}}</textarea>
I have the html below where I have a form that I want to submit to the AngularJS Controller.
<div class="newsletter color-1" id="subscribe" data-ng-controller="RegisterController">
<form name="registerForm">
<div class="col-md-6">
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required class="subscribe">
</div>
<div class="col-md-2">
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block">Subsbcribe</button>
</div>
</form>
</div>
And the controller is below
app.controller('RegisterController', function ($scope,dataFactory) {
$scope.users = dataFactory.getUsers();
$scope.register = function () {
var userEmail = $scope.userEmail;
dataFactory.insertUser(userEmail);
$scope.userEmail = null;
$scope.ThankYou = "Thank You!";
}
});
The problem is that no validation is taking place when I click the button. It is always routed to the controller although I do not supply a correct email. So every time I click the button I get the {{ThankYou}} variable displayed. Maybe I do not understand something.
AngularJS does not disable enable any functionality for form validations. What is does is, it makes the state of the form and its control in terms of validation available on the current scope. You are required to implement the behaviour yourself.
In your case if you need to check user email is valid your html input should have a name attribute like
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required class="subscribe" name='userEmail'>
Then on your controller you can check
$scope.registerForm.userEmail.$invalid property.
You can use the same property to disable the button on the form using ng-disabled
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block" ng-disabled='registerForm.userEmail.$invalid'>Subsbcribe</button>
Basically the registerForm object is a ngFormController and userEmail is ngModelController. Please read the developer guide for forms
You are missing some part to achieve what you want. Normally you will need to add some code to enable disable the submit button base on the state of the form i.e valid/invalid. In your case this can be done like that :
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block" ng-disabled="registerForm.$invalid">Subsbcribe</button>
Notice the ng-disabled="registerForm.$invalid".
You can as well provided inline feedback to the user with something like :
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required="" class="subscribe" name="userName"/>
<span ng-show="registerForm.userName.$error.required">Please enter a name</span>
Or with CSS like that :
input.ng-invalid-required {
background-color: #FA787E;
}
You have a working plunker here