I have a file upload which works, and am trying add a spinner icon to show that the file is being put into memory. The form save/submit button is disabled until the file is fully in memory. Right now I have the spinner working but it broke my button disable
previous HTML:
<div class="form-group">
<label class="col-xs-12 col-sm-4">Image <span class="required_field">*</span>:</label>
<input class="input-dnld" id="loadImg" type='file' placeholder="Select an image to upload" name="topoImg" onchange="angular.element(this).scope().readimg(this)" accept="image/*" required>
<label for="loadImg" required><span class="glyphicon glyphicon-open glyph-style"></span>Select an image to upload</label>
</div>
...
<button ng-click="saveTopo()" ng-disabled="frmNode.$invalid || !image" class="btn btn-default action_btn_style">Save</button>
current HTML:
<div class="form-group">
<label class="col-xs-12 col-sm-4">Image <span class="required_field">*</span>:</label>
<input class="input-dnld" id="loadImg" type='file' placeholder="Select an image to upload" name="topoImg" onchange="angular.element(this).scope().readimg(this)" accept="image/*" required>
<label for="loadImg" required><span class="glyphicon glyphicon-open glyph-style"></span>Select an image to upload</label>
</div>
<span style="width: 30px">
<i class="fa fa-fw fa-lg fa-spinner fa-pulse" ng-show="imgupload"></i>
</span>
...
<button ng-click="save()" ng-disabled="frmNode.$invalid || imgupload || !image" class="btn btn-default action_btn_style">Save</button>
previous JS function:
$scope.readimg = function(ele) {
$scope.image = ele.files[0];
}
current JS function:
$scope.readimg = function(ele) {
$scope.imgupload = true;
$scope.$apply();
$scope.image = ele.files[0];
$scope.imgupload = false;
$scope.$apply();
}
I've added $apply and a boolean variable to show that the image is being uploaded. Before adding the $apply the boolean from the function wasn't being changed until after the function returned. After adding the $apply the spinner shows up but the button is enabled long before the spinner disappears. I tried modifying the condition statement with the boolean value but it doesn't seem to be updating. Because of the lack of ng-change support on file type field in angularjs and me being a beginner at web dev I'm scratching my head how to make this one work.
Related
I created the following HTML form inside a jqxWindow widget for a Laravel project:
<div id="provinceWindow">
<div id="provinceWindowHeader"></div>
<div id="provinceWindowContent">
<form id="provinceForm" method="POST" action="{{route('province.store')}}">
{{ csrf_field() }}
<input type="hidden" name="provinceId" id="provinceId" value=""/>
<div class="form-group row">
<div class="col-6"><label>English province name</label></div>
<div class="col-6"><input type="text" name="provinceNameEn" id="provinceNameEn" maxlength="20"/></div>
</div>
<div class="form-group row">
<div class="col-6"><label>Spanish province name</label></div>
<div class="col-6"><input type="text" name="provinceNameSp" id="provinceNameSp" maxlength="20"/></div>
</div>
<br/>
<div class="form-group row justify-content-center">
<input type="button" value="Submit" id="submitBtn" class="btn btn-sm col-3" />
<span class="spacer"></span>
<input type="button" value="Cancel" id="cancelBtn" class="btn btn-sm col-3" />
</div>
</form>
</div>
</div>
This is the javascript file:
$(document).ready(function () {
var datarow = null;
$.ajaxSetup({
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}
});
//-----------------------------
// Window settings
//-----------------------------
$('#provinceWindow').jqxWindow({
autoOpen: false,
isModal: true,
width: 400,
height: 160,
resizable: false,
title: 'Province name',
cancelButton: $('#cancelBtn'),
initContent: function () {
$('#submitBtn').jqxButton();
$('#submitBtn').on('click', function () {
$('#provinceForm').submit();
});
}
}).css('top', '35%');
The file routes\web.php has only one resourse route defined for this page:
// Routes for province maintenance
Route::resource('province', 'provinceController');
Checking the available routes with php artisan route:list command, I get these:
Method URI Name Action
GET|HEAD / APP\Http\Controllers\homeController#index
GET|HEAD province province.index APP\Http\Controllers\provinceController#index
POST province province.store APP\Http\Controllers\provinceController#store
GET|HEAD province/create province.create APP\Http\Controllers\provinceController#create
GET|HEAD province/{province} province.show APP\Http\Controllers\provinceController#show
PUT|PATCH province/{province} province.update APP\Http\Controllers\provinceController#update
DELETE province/{province} province.destroy APP\Http\Controllers\provinceController#destroy
GET|HEAD province/{province}/edit province.edit APP\Http\Controllers\provinceController#edit
My controller action:
public function store(Request $request)
{
$fields = $request->all();
if ($request->provinceId == '') {
$province = new province($fields);
$validator = Validator::make($fields, $province->rules());
if ($validator->fails()) {
return redirect('')->withErrors($validator)->withInput();
}
else {
$province->save();
}
return view('province/index');
}
}
The form is shown on top of a jqxGrid widget, as a modal window, in order to capture the required information and perform the CRUD operations for the corresponding DB table.
The problem is, when I click the "Submit" button the window is closed and nothing else happens. The form is not posted to the indicated action and the data entered get lost.
It does not matter if I initialize the submitBtn inside the initContent or outside of it. The form is never posted.
I also tried the Close event of the jqxWindow to no avail.
If I take a look to the generated HTML it looks like this:
<form id="provinceForm" method="POST" action="http://mis:8080/province">
<input type="hidden" name="_token" value="Y9dF5PS7nUwFxHug8Ag6PHgcfR4xgxdC43KCGm07">
<input type="hidden" name="provinceId" id="provinceId" value="">
<div class="form-group row">
<div class="col-6">
<label>English province name</label>
</div>
<div class="col-6">
<input type="text" name="provinceNameEn" id="provinceNameEn" maxlength="20">
</div>
</div>
<div class="form-group row">
<div class="col-6">
<label>Spanish province name</label>
</div>
<div class="col-6">
<input type="text" name="provinceNameSp" id="provinceNameSp" maxlength="20">
</div>
</div>
<br>
<div class="form-group row justify-content-center">
<input type="button" value="Submit" id="submitBtn" class="btn btn-sm col-3 jqx-rc-all jqx-button jqx-widget jqx-fill-state-normal" role="button" aria-disabled="false">
<span class="spacer"></span>
<input type="button" value="Cancel" id="cancelBtn" class="btn btn-sm col-3">
</div>
</form>
Pressing the submit button takes me to the home page and nothing gets added to the DB table.
I guess the issue has something to do with Laravel routes because I get no errors.
What is missing or what is wrong with this approach?
Any light is appreciated.
Alright, because I erroneously added in my Model a validation, that was not needed, for a column (there was already a constraint defined at the DB table level), it was not possible to fulfill the validator when saving a new record. I commented that line in my Model and, that was it!
protected $rules = array(
'provinceNameEn' => 'required|alpha|max:20',
'provinceNameSp' => 'required|alpha|max:20'
//'deleted' => 'required|in:M,F' // This is already validated in a DB constraint.
);
I noticed the control was returned to my home page but without any message or error, but if you pay attention to my controller it was precisely the behavior programmed. However, there is no implementation to display the error messages, so I added dd($validator); before that return statement. There I read the message and finally found the solution.
my below datepicker code is like below. Its working fine. But the datepicker popup opens when i click on the input field. But want that to be open once i click on the calendar icon. Please suggest me a way to achieve that.
<div class="col-sm-6 col-md-6 col-lg-6 padleft">
<div class="form-group">
<label for="exampleSelect1">Start Date
</label>
<div class="input-group" style="width:75%">
<div class="input-group-btn">
<input type="text"
class="form-control date"
id="dateFrom"
placeholder="From"
ng-click="model.dateFrom=true"
datepicker-popup="{{model.format}}"
ng-model="model.defect.startDate"
is-open="model.dateFrom"
datepicker-options="dateOptions"
date-disabled="model.disabled(date, mode)"
ng-required="true"
close-text="Close" my-date>
<span class="btn btn-default " ng-click="model.dateFrom=true"><i class="glyphicon glyphicon-calendar"></i> </span>
</div>
</div>
</div>
</div>
In My controller :
self.format = 'MM-dd-yyyy';
self.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
self.opened = {};
self.opened[$event.target.id] = true;
// log this to check if its setting the log
console.log(self.opened);
};
Angular : 1.6
Using 'ui.bootstrap.datetimepicker',
and 'ui.bootstrap
You'll need to add ng-click="model.dateFrom=true" as an attribute to the <i> element containing your calendar icon, not its parent span.
I would actually recommend writing a separate function for toggling the datepicker on and off. Something like
$scope.toggleDatePicker = function() {
$scope.model.dateFrom = !$scope.model.dateFrom;
};
and then calling that from your html: ng-click="toggleDatePicker()"
In my rails app I have buttons that submit information to the server. Some buttons are part of a form and some are not. I'm looking for a way to apply my jquery, which disables the buttons after click, to both.
Here is my current jquery:
$('.btn-disabler').on('click', function() {
$(this).append("<i class='fa fa-spinner fa-pulse btn-loader'>").disable(true);
$(this).find('.btn-label').addClass('invisible');
});
This code adds an icon disables the button and makes the text invisible. I've extended the disable function to work on anchor tags as explained here https://stackoverflow.com/a/16788240/4584963
An example link:
<a class="btn btn-success btn-disabler" rel="nofollow" data-method="post" href="/approve?id=10">
<span class="btn-label">Approve</span>
</a>
An example form:
<form class="simple_form well" novalidate="novalidate" id="new_user" action="/" accept-charset="UTF-8" method="post">
<div class="form-group">
<input class="string optional form-control" placeholder="First name" type="text" name="user[first_name]" id="user_first_name">
</div>
<div class="form-group">
<input class="string optional form-control" placeholder="Last name" type="text" name="user[last_name]" id="user_last_name">
</div>
<div class="form-group">
<input class="string email optional form-control" placeholder="Email" type="email" name="user[email]" id="user_email">
</div>
<div class="form-group">
<input class="password optional form-control" placeholder="Password" type="password" name="user[password]" id="user_password">
</div>
<div class="form-groups">
<input class="password optional form-control" placeholder="Retype password" type="password" name="user[password_confirmation]" id="user_password_confirmation">
</div>
<button name="button" type="submit" class="btn btn btn-primary btn-disabler">
<span class="btn-label">Submit</span>
</button>
</form>
My jquery above does not work for the form. In the form on click, the button changes but there is no submission. To get the jquery to work for the form I need to change it to this:
$('.signup-form').on('submit', function() {
$(this).find('.btn-disabler').append("<i class='fa fa-spinner fa-pulse btn-loader'>").disable(true);
$(this).find('.btn-label').addClass('invisible');
});
How can I consolidate this to apply to both links and form submit buttons? Seems like my problem stems from links need the click event and the form needs the submit event.
You can use jQuery is() to check parent of current button object is form or not in order to submit the form:
$('.btn-disabler').on('click', function() {
$(this).append("<i class='fa fa-spinner fa-pulse btn-loader'>").disable(true);
$(this).find('.btn-label').addClass('invisible');
if ($(this).parent().is("form")) $(this).parent().submit();
});
do you try this using the id of the form like
$('#new_user').on('submit' ...
or with the form element
$('form').on('submit' ...
Think of the submit button as an extension of a form submit event. If you disable the form submit button, the form submit event is disabled. What you can do is add the class to the form, and then in your jQuery code you can assign specific rules. something like this..
So, using this HTML:
<form class="disabler">
<button type="submit"><span>Label</span></button>
</form>
<span>Label</span>
<button class="disabler"><span>Label</span></button>
Use this javascript:
$('.disabler').each(function(e){
if(this.nodeName == "A"){
// this is a hyperlink...
// apply css class
$(this).on('click', function(){
//some action
});
} else if (this.nodeName == "BUTTON") {
//this is a button outside of a form
// disable and add css class
$(this).on('click', function(){
//some action
});
} else if (this.nodeName == "FORM") {
$(this).on('submit', function(){
$(this).find('button[type="submit"]')
.append("<i>Loading</i>")
.disable();
});
}
});
You can probably refactor this down more, but i think you should pay attention to nodeName when you're trying to apply different rules to each of these components.
I hope this answers your question.
I am experiencing difficulties with getting a text value from bootstrap-timepicker24 form.
jsp code:
<form action="#" class="form-horizontal form-bordered" id="shop-time">
<div class="form-body form" >
<div class="form-group">
<label class="control-label col-md-4">Monday</label>
<div class="col-md-4">
<div class="input-group shop-monday-open-time">
<input type="text" class="form-control timepicker timepicker-24">
<span class="input-group-btn">
<button class="btn default" type="button">
<i class="fa fa-clock-o"></i>
</button>
</span>
</div>
</div>
</div>
js code:
// forms
var shopForm = $('#shop-time');
var shopMondayOpen = shopSave.find('.shop-monday-open-time');
// time picker listener
shopMondayOpen.on('changeTime.timepicker', function(open) {
var time = dateInUTC(open.time);
});
But the event changeTime does not affect the listener. But if I just reload the page and stop at the breakpoint on this line: var shopMondayOpen = shopSave.find('.shop-monday-open-time') line and evaluate shopMondayOpen.val at the console I get something like:
shopMondayOpen.val
jquery.min.js:4 function (a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lc,""):null==c?"":c)}}
I tried to use timepicker-24 manual but it didn't get me far..
Guess that I am missing something but I just can't figure it out.
After several days I have made a conclusion that only way you can get a value from a timepicker-24 is a value from conroler, as I have already said at tht comment to my post:
<input type="text" class="form-control timepicker timepicker-24 shop-monday-open">
var time = $('shop-monday-open').val
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 8 years ago.
Sorry for no-too-much clear title.
I'm using Twitter Bootstrap Modal to edit some record.
<a class="contact" href="#" data-form="/edit/models/sms/{{ #value['fields']['id'] }}" title="Edit">
<span class="fa-stack fa-lg">
<i class="fa fa-square-o fa-stack-2x"></i>
<i class="fa fa-pencil fa-stack-1x"></i>
</span>
</a>
And this is the javascript code that open the Modal:
$(".sms-model").click(function(ev) { // for each edit contact url
ev.preventDefault(); // prevent navigation
var url = $(this).data("form"); // get the contact form url
$("#smsModelModal").load(url, function() { // load the url into the modal
$(this).modal('show'); // display the modal on url load
});
$("#smsModelModal").modal('show'); // display the modal on url load
return false; // prevent the click propagation
});
Finally this is the form injected inside the modal:
<div class="modal-body">
<form role="form" method="post" class="sms-model-form" action="{{ #SERVER.REQUEST_URI }}">
<fieldset>
<legend class="sr-only">Edit</legend>
<input type="hidden" name="edit_id_model" value="{{ isset(#sms_model) ? #sms_model[0]['fields']['id']['value'] : '' }}" />
<div class="form-group">
<label for="title">{{ #lng_label_sms_title }}</label>
<input type="text" class="form-control required-field" name="title" value="{{ isset(#sms_model) ? #sms_model[0]['fields']['title']['value'] : '' }}"/>
</div>
<div class="form-group">
<label for="text">{{ #lng_label_sms_text }}</label>
<textarea class="form-control" name="text" class="required-field">{{ isset(#sms_model) ? #sms_model[0]['fields']['text']['value'] : '' }}</textarea>
</div>
<button type="submit" class="btn btn-white pull-right">
<i class="fa fa-plus-circle"></i> {{ isset(#sms_model) ? #lng_btn_edit : #lng_btn_add }}
</button>
<input type="submit" class="btn btn-primary" value="Test" />
</fieldset>
</form>
</div>
Everything functions as a charme. Now I would submit the form via AJAX.
So I'm adding this:
$('.sms-model-form').on('submit', function(e) {
console.log('test on submit....');
e.preventDefault();
$.ajax({
type: $(this).attr('method'),
url: this.action,
data: $(this).serialize()+'&ajax=TRUE',
context: this,
success: function(data, status) {
$('#smsModelModal').html(data);
}
});
return false;
});
But form is submitted via regular mode, and not via AJAX. I.e. I don't have neither the event logged in console.
I'm thinking that this is because the form is injected in a second moment in the page and not at
$(document).ready(function() {
Am I right? How I can solve my issue?
You almost certainly need to set up your event handler via delegation:
$(document).on('submit', '.sms-model-form', function(e) {
That attaches a handler at the root of the DOM to catch bubbling "submit" events. Because you're adding your modal dialog content after your code runs, if you do it your way the code will simply have no effect; the ".sms-model-form" selector will match nothing, so no event handler will be attached anywhere.
Using the above form of .on(), you ensure that events involving DOM substructures added dynamically will still be handled as you desire them to be.