knockout update unit price when product combo changes - select

I have this table bounded to knockout like this
<tbody data-bind="foreach: Items">
<tr class="gradeA">
<td>
<select name="MaterialId" data-bind="options: $parent.lookups.materials, optionsText: 'Name', value: Material"></select></td>
<td>
<input type="text" name="Quantity" data-bind="value: Quantity"></td>
<td>
<input type="text" name="UnitPrice" data-bind="value: UnitPrice"></td>
<td>
<input type="text" name="Discount" data-bind="value: Discount"></td>
<td>
<input type="text" readonly="readonly" data-bind="value: Price" />
</td>
</tr>
</tbody>
javascript is:
function Item() {
this.Material = ko.observable()
this.Quantity = ko.observable(1)
this.UnitPrice = ko.observable(0)
this.Discount = ko.observable(0)
this.MaterialRetailPrice = ko.computed(function () {
return this.Material() ? this.Material().RetailPrice : 0
}, this);
this.StoreId = ko.computed(function () {
return this.Store() ? this.Store().Id : 0
}, this)
this.Price = ko.computed(function () {
return this.Quantity() * this.UnitPrice() - this.Discount()
}, this)
}
function materialBuyBillViewModel() {
var self = this
self.lookups = {
stores: ko.observableArray([]),
materials: ko.observableArray([])
}
self.Items = ko.observableArray()
self.VendorBill = ko.observable()
self.Vendor = ko.observable()
self.Discount = ko.observable()
self.Vat = ko.observable()
//... Methods to fill lookups
}
$(document).ajaxStop(function (event, request, settings) {
MaterialBuyBillViewModel.AddItem()
})
$(document).ready(function () {
MaterialBuyBillViewModel = new materialBuyBillViewModel()
})
The result is fine and I can change the unit price and get price updated, but the missing thing is to get unit price changed and price updated when product select is changed (replace unitprice value with Material().RetailPrice). any one can point me how to bind unit price input properly?

I hope I got your question correctly.
You can create a ko.computed with a read and write method.
The read method enables you to check if a material is selected. If there is, you return the price of the selected material. If there isn't, you return the user defined UnitPrice value.
The write method just forwards the user input straight to the UnitPrice property. To indicate that, when a material is selected, the user cannot define the value, I've added a disabled binding on the input field.
Let me know if this solves your problem.
function Item() {
this.Material = ko.observable();
this.Quantity = ko.observable(5);
this.UnitPrice = ko.observable(1);
this.Discount = ko.observable(0);
this.ComputedUnitPrice = ko.computed({
read: function() {
return this.Material() ? this.Material().RetailPrice : this.UnitPrice();
},
write: function(val) {
this.UnitPrice(val);
},
owner: this
});
this.Price = ko.computed(function() {
return this.Quantity() * this.ComputedUnitPrice() - this.Discount()
}, this);
}
function materialBuyBillViewModel() {
var self = this;
self.lookups = {
materials: ko.observableArray([{
Name: "Material 1",
RetailPrice: 1
}, {
Name: "Material 2",
RetailPrice: 2
}, {
Name: "Material 3",
RetailPrice: 3
}])
};
self.Items = ko.observableArray([
new Item()
]);
};
ko.applyBindings(new materialBuyBillViewModel());
[disabled] {
background: #efefef
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table>
<thead>
<tr>
<th>Material</th>
<th>Quantity</th>
<th>UnitPrice</th>
<th>Discount</th>
<th>Price</th>
</tr>
</thead>
<tbody data-bind="foreach: Items">
<tr class="gradeA">
<td>
<select name="MaterialId" data-bind="options: $parent.lookups.materials, optionsText: 'Name', optionsCaption: 'Pick a material', value: Material, allowValueUnset: true"></select>
</td>
<td>
<input type="text" name="Quantity" data-bind="value: Quantity">
</td>
<td>
<input type="text" name="UnitPrice" data-bind="value: ComputedUnitPrice, disable: Material">
</td>
<td>
<input type="text" name="Discount" data-bind="value: Discount">
</td>
<td>
<input type="text" readonly="readonly" data-bind="value: Price" />
</td>
</tr>
</tbody>
</table>

Related

Angular2 Reactive Form Table

I am having some trouble looking up and attempting to do what I want to.
I have a table with inputs in each row, and I want each row which is created using an ngFor, to be considered a form group.
Within each form group I want a validation in that if any of the controls are filled within the row, that the entire form group needs to be filled before submission can be done.
Here is what I have so far in my template.
I don't have anything in the component yet as Angular.io and searching around for a few hours has not shown me anything close to what I want.
<form>
<table id="table" class="mdl-data-table mdl-js-data-table mdl-data-table mdl-shadow--2dp">
<thead>
<tr>
<th>Day</th>
<th>Description</th>
<th>Open Time</th>
<th>Close Time</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let scheduleDetail of scheduleDetails">
<td style="padding: 0 8px 0 8px;">{{weekdayConverter(scheduleDetail.dayId)}}</td>
<td class="pad-input">
<mdl-textfield style="max-width:100px;" type="text" class="font" name="description" [(ngModel)]="scheduleDetail.description"></mdl-textfield>
</td>
<td>
<mdl-textfield style="max-width:75px" type="text" error-msg="hh:mm" name="openTime" pattern="([01]\d|2[0-3]):?([0-5]\d)" [(ngModel)]="scheduleDetail.openTime"></mdl-textfield>
</td>
<td>
<mdl-textfield style="max-width:75px" type="text" error-msg="hh:mm" name="closeTime" pattern="([01]\d|2[0-3]):?([0-5]\d)" [(ngModel)]="scheduleDetail.closeTime"></mdl-textfield>
</td>
</tr>
</tbody>
</table>
</form>
Update
Added the following to the template:
Changed inputs to:
<mdl-textfield (keyup)="formChange(scheduleDetail)" style="max-width:100px;" type="text" class="font" name="description" [(ngModel)]="scheduleDetail.description"></mdl-textfield>
Added the following to the component:
formChange(detail:scheduleDetail){
if(this.checkValid(detail)==false)
this.scheduleDetails.filter(detail => detail == detail)[0].require=true;
else
this.scheduleDetails.filter(detail => detail == detail)[0].require=false;
this.checkForm();
}
checkValid(detail:scheduleDetail){
if(detail.description!=null && detail.description!=""){
if(this.checkTime(detail))
return true
else
return false
}
else
return true
}
checkTime(detail:scheduleDetail){
if(
(detail.openTime!=null && detail.closeTime!=null) &&
( detail.openTime!="" && detail.closeTime!="") &&
(this.checkRegExp(detail.openTime) && this.checkRegExp(detail.closeTime))
){
return true
}
else if((this.checkRegExp(detail.openTime) && this.checkRegExp(detail.closeTime))){
return true
}
else return false
}
checkRegExp(time:string){
let timeRegExp = /([01]\d|2[0-3]):?([0-5]\d)/;
if(timeRegExp.test(time)){
return true;
}
else
return false;
}
checkForm(){
let valid: boolean = true;
this.scheduleDetails.forEach(detail => {
if(detail.require==true){
valid = false;
}
});
this.scheduleDetails.forEach(detail => {
if(detail.description=="" || detail.description==null){
valid = false;
}
});
this.formValid = valid;
}
Model Driven Forms
You are using a template driven form, which is hard to scale, and maintain.
Here, i will guide you to migrate to a model driven form.
Component
export class WeekScheduleComponent {
// Our empty Form
myForm: FormGroup;
constructor(private fb: FormBuilder){
// We inject FormBuilder to our component
// Now, we instantiate myForm with FormBuilder
// Notice that myForm is a FormGroup which contains an empty FormArray
this.myForm = this.fb.group({
scheduleDetail: this.fb.array([])
})
}
addRow(){
// This function instantiates a FormGroup for each day
// and pushes it to our FormArray
// We get our FormArray
const control = <FormArray>this.myForm.controls['scheduleDetail'];
// instantiate a new day FormGroup;
newDayGroup: FormGroup = this.initItems();
// Add it to our formArray
control.push(newDayGroup);
}
initItems(): FormGroup{
// Here, we make the form for each day
return this.fb.group({
description: [null, Validators.required],
openTime: [null, Validators.required],
closeTime: [null, Validators.required]
});
}
submit(){
// do stuff and submit result
console.log(this.myForm.value);
}
}
in your template:
<form [formGroup]="myForm" *ngIf="myForm">
<table formArrayName="scheduleDetail">
<tr *ngFor="let item of myForm.controls.scheduleDetail.controls; let i=index"
[formGroupName]="i" >
<td><input type='text' formControlName="description"></td>
<td><input type='text' formControlName="openTime"></td>
<td><input type='text' formControlName="closeTime"></td>
</tr>
</table>
</form>
<button (click)="addRow()">Add new item</button>
<button (click)="submit()" [disabled]="!myForm.valid">Submit</button>
Component
import { Component, OnInit } from '#angular/core';
import {FormGroup, FormBuilder, FormControl, Validators, FormArray} from '#angular/forms';
#Component({
selector: 'app-sales',
templateUrl: './sales.component.html',
styleUrls: ['./sales.component.css']
})
export class SalesComponent implements OnInit {
myForm: FormGroup;
constructor(private fb: FormBuilder){
}
// getter to get a reference to scheduleDetail form array in myForm form group
get scheduleDetail():FormArray{
return <FormArray>this.myForm.get('scheduleDetail')
}
// add a new row, get reference to form array using getter method and push form group into it
addRow(){
this.scheduleDetail.push(this.initItems());
}
// make a form for each row!
initItems(): FormGroup{
return this.fb.group({
description: [null, Validators.required],
openTime: [null, Validators.required],
closeTime: [null, Validators.required]
});
}
submit(){
console.log(this.myForm.value)
}
ngOnInit() {
this.myForm = this.fb.group({
scheduleDetail: this.fb.array([this.initItems()])
})
}
}
Template
<form [formGroup]="myForm" *ngIf="myForm">
<table formArrayName="scheduleDetail">
<thead>
<tr>
<th >Desc</th>
<th >Open Time</th>
<th >Close Time</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of myForm.controls.scheduleDetail.controls; let i=index"
[formGroupName]="i" >
<td><input type='text' formControlName="description"></td>
<td><input type='text' formControlName="openTime"></td>
<td><input type='text' formControlName="closeTime"></td>
</tr>
</tbody>
</table>
</form>
<button (click)="addRow()">Add new item</button>
<button (click)="submit()" [disabled]="!myForm.valid">Submit</button>

dropdown will accept a value that is not part of the list as well in Knockout

When entering an E-mail address, the user will have to select the E-mail
domain from the pre-defined list (e.g., gmail.com; outlook.com; hotmail.com).
The Domain dropdown will accept a value that is not part of the list as well.
I should have both select and input feature.
HTML:
<!-- Mulitple array of emails -->
<div>
<table class="table table-bordered">
<tbody data-bind='foreach: billDeliveryEmails'>
<tr>
<td><input class='required' data-bind='value: userName' /></td>
<td><select data-bind="options: $root.availableEmailDomains(), value: domainName, optionsText: 'domainName', optionsValue: 'domainName'"></select></td>
<td><a data-bind="click:'removeDeliveryEmailAddress'">Delete</a></td>
</tr>
</tbody>
</table>
<a class="atm-bloque-link" data-bind="click:'addDeliveryEmailAddress'">Agregue otra direccion de email</a>
</div>
VM:
// Domain class
function Domain(domainName) {
var self = this;
self.domainName = domainName;
}
billDeliveryEmails : [],
availableEmailDomains : ko.observableArray([
new Domain("hotmail.com"),
new Domain("yahoo.com")
])
addDeliveryEmailAddress: function ($element, data, context, bindingContext, event) {
bindingContext.$root.billDeliveryEmails.push({
userName: "",
domainName: this.viewModel.get('availableEmailDomains')[0]
});
event.preventDefault();
},
removeDeliveryEmailAddress: function ($element, data, context, bindingContext, event) {
bindingContext.$root.billDeliveryEmails.splice(0, 1)
event.preventDefault();
}
Based on the link in your comment, here's an example:
function Domain(domainName) {
var self = this;
self.domainName = domainName;
}
var vm = function () {
var self = this;
self.browser = ko.observable();
self.browserList = ko.observableArray([
new Domain('yahoo.com'),
new Domain('hotmail.com')
])
}();
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<label>Choose a browser from this list:
<input list="browsers" name="myBrowser" data-bind="value: browser" /></label>
<datalist id="browsers" data-bind="foreach: browserList">
<option data-bind="text: domainName">
</datalist>
<br />
Your browser is: <span data-bind="text: browser"></span>
An observable array is used to populate the list and a regular observable tracks the selected value.

How to handle one to many relation ship Knockout-Entity Framework

So I have I have a simple structure where one purchase have a collection of expenses, and each expense have an account(plastic, cash, plastic#2...).
So the json my api gets is similar to this:
[
{"$id":"1","Id":1,"Name":"apple","Value":100.0,"AccountId":1,"Account":
{"$id":"2","Id":1,"Name":"Cash"}},
{"$id":"3","Id":2,"Name":"pear","Value":50.0,"AccountId":1,"Account":
{"$ref":"2"}},
{"$id":"4","Id":3,"Name":"raspberry","Value":10.0,"AccountId":1,"Account":
{"$ref":"2"}}
]
I see my json is not writing my cash account each time it needs it, it is refering it with
{"$ref":"2"}
where
{"$id":"2","Id":1,"Name":"Cash"}
so when I render my table with this html:
<table>
<tbody data-bind="foreach: gastos">
<tr>
<td data-bind="text: $data.id"></td>
<td data-bind="text: $data.name"></td>
<td data-bind="text: $data.value"></td>
<td data-bind="text: $data.account.Name"></td>
<td>
<button type="button" class="btn btn-xs">
<i class="glyphicon glyphicon-trash"></i>
</button>
</td>
</tr>
</tbody>
</table>
I get this, because the account for pear, and raspberry are nulls:
So how do you handle $ref in knockout?
I am mapping to 'gastos' this way:
$.getJSON('#ViewBag.GastosUrl', function (data) {
data.forEach(function(o) {
gastos.push(new gastoVM(o.Id, o.Name, o.Value, o.Account));
});
});
var gastoVM = function(Id, Name, Value, Account) {
var self = this;
self.id = Id;
self.name = Name;
self.value = Value;
self.account = Account;
};
thanks.
I'm not familiar with entity-framework but with the data as provided, a couple options available (JSFiddle):
Build up the account information alongside the gastos. And only provide the $id or $ref for later referencing.
var vm = {
gastos: [],
accounts: {},
accountLookup: function(accountId){
return this.accounts[accountId];
}
}
//... inside AJAX call
var accountId = o.Account["$id"]
if(accountId)
{
vm.accounts[accountId] = o.Account;
}
Use a ko utility method to lookup the account from within your array.
accountLookupByUtil: function(accountId) {
var gasto = ko.utils.arrayFirst(this.gastos, function(item) {
if(item.account['$id'] == accountId)
{
return item
}
});
return gasto.account;
}
From the html:
<td data-bind="text: $root.accountLookup($data.accountId).Name"></td>
<td data-bind="text: $root.accountLookupByUtil($data.accountId).Name"></td>
Note: Both methods are available in the fiddle, thus some properties are provided that would not be necessary depending upon the method used.

Button redirecting to the grid page

I have a custom module 'banner' and in which I have added a button in its second tab(only two tabs for the module). when click on that button, it is submitting my banner automatically and then go to the grid page(i e it acts as just another save button). But the function of this button is to add an uploading image field.ie whenever the button is clicked, it should add an image form field to my tab file. This is my tab file.
<?php
class Karaokeshop_Banner_Block_Adminhtml_Banner_Edit_Tab_Image extends Mage_Adminhtml_Block_Widget_Form
{
protected function _prepareForm()
{
$form = new Varien_Data_Form();
$this->setForm($form);
$fieldset = $form->addFieldset('banner_image', array('legend'=>Mage::helper('banner')->__('Banner Image')));
//declaring a new custom form field and adding
$fieldset->addType('add_button', 'Karaokeshop_Banner_Block_Adminhtml_Banner_Edit_Tab_Field_Custom');
$fieldset->addField('banner_img_add_button', 'add_button', array(
'title' => Mage::helper('banner')->__('Add Banner Image'),
'id' => 'add_banner_img_button',
'class' => 'scalable save',
'style' => '',
'onclick' => 'banner.add(this)',
'type' => 'button',
));
return parent::_prepareForm();
}
}
this is my button defining file
<?php
class Karaokeshop_Banner_Block_Adminhtml_Banner_Edit_Tab_Field_Custom extends Varien_Data_Form_Element_Abstract
{
public function __construct($attributes=array())
{
parent::__construct($attributes);
}
public function getElementHtml()
{
$value = $this->getTitle();
$onclick=$this->getOnclick();
$class=$this->getClass();
$id=$this->getId();
$style=$this->getStyle();
$type=$this->getType();
$html='<button id="'.$id.'" class="'.$class.'" style="'.$style.'" onclick="'.$onclick.'" type="'.$type.'" title="'.$value.'">'.$value.' </button>';
$html .= '<p id="' . $this->getHtmlId() . '"'. $this->serialize($this->getHtmlAttributes()) .'>
<script type="text/javascript">
//<![CDATA[
var banner =
{
add : function(obj)
{
},
};
//]]>
</script>
</p>';
return $html;
}
}
what should i do to change my button to an add button? what should I do to avoid this submitting functionality of the button. Please help me. Thanks in advance
First you need to call your phtml from block like this :
class My_Moudles_Block_Adminhtml_Image_Edit_Tab_Form extends Mage_Adminhtml_Block_Widget_Form
{
public function __construct()
{
parent::__construct();
$this->setTemplate('modules/imageupload.phtml');
$this->setFormAction(Mage::getUrl('*/*/imageupload'));
}
then create file in adminhtml/default/default/template/yourmodule/imageupload.phtml and put this code there.
<div class="entry-edit">
<div class="entry-edit-head">
<h4 class="icon-head head-edit-form fieldset-legend"><?php echo $this->__('General')?></h4>
<div class="form-buttons"></div>
</div>
<form id="imageform" method="post" action="<? echo $this->getFormAction(); ?>">
<div id="rules_form" class="fieldset ">
<div class="hor-scroll">
<table cellspacing="0" class="form-list">
<tbody>
<tr>
<td class="label"><?php echo $this->__('Add Image')?></td>
<td class="grid tier" colspan="10">
<table cellspacing="0" id="chain_tiers" class="chain border" style=" width:465px; ">
<thead>
<tr class="headings">
<th><?php echo $this->__('Image')?></th>
<th class="last"><?php echo $this->__('Action')?></th>
</tr>
<tr class="template no-display" id="email_chain_add_template">
<td class="nobr">
<input type="file" id="chain_Image" value="0" name="imageg" class="requried-entry input-text">
</td>
<td class="last"><input type="hidden" value="" disabled="no-template" class="delete" name="email_chain[__index__][delete]"><button onclick="emailsControl.deleteItem(event);return false" class="scalable delete icon-btn delete-product-option" title="Delete Image"><span><?php echo $this->__('Delete')?></span></button></td>
</tr>
</thead>
<tfoot>
<tr>
<td></td>
<td class="a-right" colspan="6">
<button style="" onclick="emailsControl.addItem()" class="scalable add" type="button" title="Add email" id="id"><span><span><span><?php echo $this->__('Add Image')?></span></span></span></button></td>
</tr>
</tfoot>
<tbody id="email_chain_container">
<tr>
<td class="nobr">
<input type="file" id="chain_Image" value="" name="Image[]" class="input-text">
</td>
<td class="last"><input type="hidden" value="" class="delete" name="email_chain[delete][]"><button onclick="emailsControl.deleteItem(event);return false" class="scalable delete icon-btn delete-product-option" title="Delete Image"><span><?php echo $this->__('Delete')?></span></button></td>
</tr>
</tbody>
</table>
<script type="text/javascript">
//<![Cchain[
var emailsControl = {
itemsCount : 0,
deleteButton : false,
addItem : function () {
var chain = {};
chain.TEMPLATE_ID = 0;
chain.index = this.itemsCount++;
if (arguments.length == 1) {
chain.TEMPLATE_ID = arguments[0];
}
var s = '<tr>' + $('email_chain_add_template').innerHTML.replace(/__index__/g, '#{index}').replace(/\sdisabled="?no-template"?/g, ' ').replace(/disabled/g, ' ').replace(/="'([^']*)'"/g, '="$1"') + '</tr>';
var template = new Template(s);
Element.insert($('email_chain_container'), {'bottom': template.evaluate(chain)});
$('chain_row_'+chain.index+'_TEMPLATE').value = chain.TEMPLATE_ID;
maxItemsCount++;
},
deleteItem : function(event) {
var tr = Event.findElement(event, 'tr');
if (tr) {
jQuery(tr).remove();
}
}
}
var maxItemsCount = 2;
//]]>
</script>
</td>
</tr>
</tbody>
</table>
</div></form>
</div>
</div>
Hopes this will solve your issue.
For edit you can do it like this :
<tbody id="email_chain_container">
<?php foreach($images as $row){ ?><tr>
<td class="nobr">
your image code
</td></tr>

jquery validation with modal formwith ajax submitHandler

I have a form within a modal that i am trying to validate before the form gets submitted to ajax db etc.
I am trying to validate the form $("#new_request_form").validate({ on the save button. if it validate then submit the form.
Can anybody tell me what i am missing?
Thanks in advance!
$(document).ready(dialogForms);
function dialogForms() {
$('a.menubutton').click(function() {
var a = $(this);
$.get(a.attr('href'),function(resp){
var dialog = $('<div>').attr('id','formDialog').html($(resp).find('form:first').parent('div').html());
$('body').append(dialog);
dialog.find(':submit').hide();
dialog.dialog({
title: a.attr('title') ? a.attr('title') : '',
modal: true,
buttons: {
'Save': function() {
$("#new_request_form").validate({
submitHandler: function(form) {
submitFormWithAjax($(this).find('form'));
$(this).dialog('close');
}
});
},
'Cancel': function() {$(this).dialog('close');}
},
close: function() {$(this).remove();},
width: 600,
height: 500,
show: "fade",
hide: "fade"
});
var $ac_start_date = '<?php echo $ac_end_date ?>',
$ac_start_date_flip = '<?php echo $ac_end_date_flip ?>',
$ac_start_parsed = Date.parse($ac_start_date),
_today = new Date().getTime();
// For Opera and older winXP IE n such
if (isNaN($ac_start_parsed)) {
$ac_start_parsed = Date.parse($ac_start_date_flip);
}
var _aDayinMS = 1000 * 60 * 60 * 24;
// Calculate the difference in milliseconds
var difference_ms = Math.abs($ac_start_parsed - _today);
// Convert back to days and return
var DAY_DIFFERENCE = Math.round(difference_ms/_aDayinMS);
// do initialization here
$("#startdate").datepicker({
dateFormat: 'dd-mm-yy',
changeMonth: true,
changeYear: true,
yearRange: '0:+100',
minDate: '+1d',
maxDate: '+' + (DAY_DIFFERENCE + 1) + 'd'
});
// do initialization here
$("#enddate").datepicker({
dateFormat: 'dd-mm-yy',
changeMonth: true,
changeYear: true,
yearRange: '0:+100',
minDate: '+1d',
maxDate: '+' + (DAY_DIFFERENCE + 1) + 'd'
});
}, 'html');
return false;
});
}
function submitFormWithAjax(form) {
form = $(form);
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: (form.attr('method')),
dataType: 'script',
success: function(data){
$(this).dialog('close');
// Refresh table
}
});
return false;
}
FORM
<?php
require_once("../config.php");
include_once("scripts/connection.php");
?>
<p class="validateTips">All form fields are required.</p>
<div>
<form id="new_request_form" action="insert_new_request.php" method="POST" class="new_request">
<fieldset>
<legend><p class="subheadertext">Request Holiday</p></legend>
<table width="100%" border="0">
<?php
$username = $USER->firstname.' '.$USER->lastname;
$is_academic_result = mysql_query('SELECT * FROM holiday_entitlement_academic WHERE employee = \'' . $username . '\'');
if($is_academic = mysql_fetch_array($is_academic_result)) {
switch($is_academic['units']) {
case 'days':
echo'<tr>
<td width="150px" valign="middle"><label for="days">Days:</label></td>
<td valign="top">
<select id="days" name="days">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</td>
</tr>
<tr>
<td width="150px" valign="middle"><label for="startdate">Start Date:</label></td>
<td valign="top"><input type="text" name="startdate" id="startdate" class="required" readonly="readonly"/></td>
</tr>';
break;
case 'hours':
echo'<tr>
<td width="150px" valign="middle"><label for="days">Hours:</label></td>
<td valign="top"><input type="text" name="hours" id="hours" class="required" /></td>
</tr>
<tr>
<td width="150px" valign="middle"><label for="startdate">Start Date:</label></td>
<td valign="top"><input type="text" name="startdate" id="startdate" class="required" readonly="readonly"/></td>
</tr>
<tr>
<td width="150px" valign="middle"><label for="startdate">End Date:</label></td>
<td valign="top"><input type="text" name="enddate" id="enddate" class="required" readonly="readonly"/></td>
</tr>';
break;
default:
break;
}
}
?>
</table>
<input type="hidden" id="acyear" name="acyear" value="<?php echo $academic_start_date; ?>"/>
<input type="hidden" id="user" name="user" value="<?php echo $USER->id; ?>"/>
<input type="hidden" id="employee" name="employee" value="<?php echo $USER->firstname.' '.$USER->lastname; ?>"/>
</fieldset>
</form>
</div>
EDIT - What it does
with the following when you click save it does not do anything, the modal stays up and even if you fill the form it does not do anything:
'Save': function() {
$("#new_request_form").validate({
submitHandler: function(form) {
submitFormWithAjax($(this).find('form'));
$(this).dialog('close');
}
});
},
With the following the form gets submitted and works as expected just no validation:
'Save': function() {
submitFormWithAjax($(this).find('form'));
$(this).dialog('close');
},
I guess when calling submitHandler function, you have passed the wrong selector. $(this) represent the form itself so there is no need to find the form in it.
So Replace this code
submitFormWithAjax($(this).find('form'));
With
submitFormWithAjax($(this));
Or Alternately
submitFormWithAjax($("#new_request_form"));
This will fix you problem.