IE automation - Excel Vba can't save value when click save button - excel

I am trying to do IE Automation through Excel VBA code.
I have a web page which has cells to add value. I need to change values in these cells by code vba excel
example:
Now cells in webpage has value : "11_now test"
My code vba excel:
ie.Document.getelementbyid("mx7125[R:0"]").Value = "Good" ' value i want to set
When run vba , webpage show value at cell is "Good" but when i click save button, the value at cell is "11_now_test"
HTML code is as below:
<input aria-labelledby="" id="mx7125[R:0]" class="fld text tt" ctype="textbox" li="mx7126[R:0]" db="mx5134" maxlength="200" style=";width:300px;" ontr='true' async='1' ae="setvalue" type="text" title="Remark: 11_now_test" value="11_now_test" ov="11_now_test" work="1" fldInfo='{"length":"200","inttype":"0"}'/></div><div aria-live="polite" id="mx7126[R:0]_holder" class="bc"><img sf="1" aria-hidden="true" active="0" ctype="image" alt="" src="../webclient/skins/skins-20171010-1330/tivoli09/images/blank.gif" source="blank" imgtype=".gif" style="display:inline;margin:0px;" border="0" lc="mx7125[R:0]" align="absmiddle" width='0px' height='26px' id="mx7126[R:0]" title=""/></div></td>
* More information*
Dear bros
when i press F12 to inspector on webpage. If click to change value on webpage, html code at this time is:
<input aria-labelledby="" id="mx7125[R:0]" class="fld text tt" ctype="textbox" li="mx7126[R:0]" db="mx5134" maxlength="200" style=";width:300px;" ontr="true" async="1" ae="setvalue" type="text" title="Remark: 11 Nov test" value="11 Nov test" ov="11 Nov test" work="1" fldinfo="{"length":"200","inttype":"0"}" originalvalue="11 Nov test" prekeyvalue="good" stoptcclick="true" keydown="false" changed_by_user="true" changed="true">
When type value " Good" to input cell on webpage ,prekeyvalue ="Good" and keydown will turn "True" then keydown back to "false"
* Javascrip at input cell *
when click to change value at input cell i found javascrip :
function tb_(eventOrComponent)
{
eventOrComponent = (eventOrComponent) ? eventOrComponent : ((window.event) ? window.event : "");
var eventType = eventOrComponent.type;
var textbox = this;
if(undef(eventType) || eventType=="text") {
eventType = "init";
textbox = eventOrComponent;
}
if(DESIGNMODE)
return;
var ro = textbox.readOnly;
var exc=(textbox.getAttribute("exc")=="1");
switch(eventType)
{
case "init":
setPromptValue(textbox.id);
break;
case "mousedown":
if(getFocusId()==this.id)
this.setAttribute("stoptcclick","true");
break;
case "mouseup":
if (isIE() && !hasFocus(this))
{
this.focus();
}
if (isBidiEnabled)
{
adjustCaret(eventOrComponent, this);
}
break;
case "blur":
input_onblur(eventOrComponent,this);
if (isBidiEnabled)
input_bidi_onblur(eventOrComponent, this);
break;
case "change":
if(!ro)
input_changed(eventOrComponent,this);
break;
case "click":
if(overError(eventOrComponent,this))
showFieldError(eventOrComponent,this,true);
var liclick=this.getAttribute("liclick");
var li=this.getAttribute("li");
if(li!="" && liclick=="1")
{
frontEndEvent(getElement(li),'click');
}
if(this.getAttribute("stoptcclick")=="true")
{
eventOrComponent.cancelBubble=true;
}
this.setAttribute("stoptcclick","false");
break;
case "focus":
input_onfocus(eventOrComponent,this);
if (isBidiEnabled)
input_bidi_onfocus(eventOrComponent, this);
this.select();
this.setAttribute("prekeyvalue",this.value);
break;
case "keydown":
this.setAttribute("keydown","true");
if(!ro)
{
lastKeyPress = eventOrComponent.keyCode;
if(eventOrComponent.ctrlKey && hasKeyCode(eventOrComponent,'KEYCODE_SPACEBAR')) {
stopBubble(eventOrComponent);
eventOrComponent.cancelBubble=true;
eventOrComponent.returnValue=false;
break;
}
if(isBidiEnabled)
processBackspaceDelete(eventOrComponent,this);
if(hasKeyCode(eventOrComponent, 'KEYCODE_DELETE') || hasKeyCode(eventOrComponent, 'KEYCODE_BACKSPACE'))
{
getHiddenForm().elements.namedItem("changedcomponentvalue").value = this.value;
}
if((hasKeyCode(eventOrComponent, 'KEYCODE_TAB') || hasKeyCode(eventOrComponent, 'KEYCODE_ESC')))
{
var taMatch = dojo.attr(this, "ta_match");
if(taMatch) {
if(taMatch.toLowerCase().indexOf(this.value.toLowerCase()) == 0)
{
console.log("tamatch="+taMatch);
this.value = taMatch;
input_keydown(eventOrComponent, this);
dojo.attr(this, {"prekeyvalue" : ""});
input_forceChanged(this);
inputchanged = false;
return; // don't want to do input_keydown again so preKeyValue will work
}
}
if(this.getAttribute("PopupType"))
{
var popup = dijit.byId(dojohelper.getPopupId(this));
if (popup)
{
dojohelper.closePickerPopup(popup);
if(hasKeyCode(eventOrComponent, 'KEYCODE_ESC'))
{
if (eventOrComponent.preventDefault)
{
eventOrComponent.preventDefault();
}
else
{
eventOrComponent.returnValue = false;
}
return;
}
}
}
}
input_keydown(eventOrComponent,this);
datespin(eventOrComponent,this);
}
else if(hasKeyCode(eventOrComponent,'KEYCODE_ENTER') || (hasKeyCode(eventOrComponent,'KEYCODE_DOWN_ARROW') && this.getAttribute("liclick")))
{
var lbId = this.getAttribute("li");
frontEndEvent(getElement(lbId), 'click');
}
else if(hasKeyCode(eventOrComponent,KEYCODE_BACKSPACE))
{
eventOrComponent.cancelBubble=true;
eventOrComponent.returnValue=false;
}
break;
case "keypress":
if(!ro)
{
lastKeyPress = eventOrComponent.keyCode;
if(eventOrComponent.ctrlKey==false && hasKeyCode(eventOrComponent,'KEYCODE_ENTER'))
{
var db = this.getAttribute("db");
if(db && db!="")
{
input_forceChanged(this);
sendClick(db);
// IV32363 - When default button is a new row button, then we must set focus on
// the button or the value in text box will be copied to the new row
if (db)
{
window.setTimeout("focusElement(document.getElementById('"+db+"'))", 10);
}
}
}
}
break;
case "keyup":
var keyDown = this.getAttribute("keydown");
this.setAttribute("keydown","false");
if(eventOrComponent.ctrlKey && hasKeyCode(eventOrComponent,'KEYCODE_SPACEBAR'))
{
if(showFieldError(eventOrComponent,this,true))
{
return;
}
else
{
menus.typeAhead(this,0);
}
}
if(!ro)
{
if(isBidiEnabled)
processBidiKeys(eventOrComponent,this);
numericcheck(eventOrComponent,this);
var min = this.getAttribute("min");
var max = this.getAttribute("max");
if(min && max && min!="NONE" || max!="NONE")
{
if(min!="NONE" && parseInt(this.value)<parseInt(min))
{
this.value=min;
getHiddenForm().elements.namedItem("changedcomponentvalue").value = this.value;
this.select();
return false;
}
if(max!="NONE" && parseInt(this.value)>parseInt(max))
{
this.value=max;
getHiddenForm().elements.namedItem("changedcomponentvalue").value = this.value;
this.select();
return false;
}
}
var defaultButton = false;
if(eventOrComponent.ctrlKey==false && hasKeyCode(eventOrComponent,'KEYCODE_ENTER'))
{
var db = this.getAttribute("db");
if(db && db!="")
{
defaultButton=true;
}
}
input_changed(eventOrComponent,this);
}
else
{
setFocusId(eventOrComponent,this);
}
if(showFieldHelp(eventOrComponent, this))
{
return;
}
if(keyDown=="true" && hasKeyCode(eventOrComponent, 'KEYCODE_ENTER') && !eventOrComponent.ctrlKey && !eventOrComponent.altKey)
{
menus.typeAhead(this,0);
return;
}
if(!hasKeyCode(eventOrComponent, 'KEYCODE_ENTER|KEYCODE_SHIFT|KEYCODE_CTRL|KEYCODE_ESC|KEYCODE_ALT|KEYCODE_TAB|KEYCODE_END|KEYCODE_HOME|KEYCODE_RIGHT_ARROW|KEYCODE_LEFT_ARROW')
&& !eventOrComponent.ctrlKey && !eventOrComponent.altKey)
{
menus.typeAhead(this,0);
}
break;
case "mousemove":
overError(eventOrComponent,this);
break;
case "drop":
input_onfocus(eventOrComponent,this);
if (isBidiEnabled)
{
input_bidi_onfocus(eventOrComponent, this);
}
this.select();
if(!ro)
{
this.setAttribute("prekeyvalue",this.value);
}
case "cut":
case "paste":
if(!ro)
{
var fldInfo = this.getAttribute("fldInfo");
if(fldInfo)
{
fldInfo = dojo.fromJson(fldInfo);
if(!fldInfo.query || fldInfo.query!=true)
{
setButtonEnabled(saveButton,true);
}
}
window.setTimeout("inputchanged=true;input_forceChanged(dojo.byId('"+this.id+"'));", 20);
}
break;
}
}
* HIDDEN FORM *
Dear #Zhi Lv - MSFT ! i tried sendkeys method but not success! i found the same problem at this link. Extractly that i want to change value in maximo website, has hiddenform but at that linked they use javascript, don't use IE automation vba excel.When i inspect at input cells and type document.getelementbyid("hiddenform") , found this hiddenform:
<form aria-hidden="true" id="hiddenform" name="hiddenform" method="POST" action="http://maximo.mysite.com/maximo/ui/maximo.jsp" style="padding:3px;">
<input type="text" size="45" name="event" id="event" title="event type"><br>
<input type="text" size="45" name="targetid" id="targetid" title="target id"><br>
<input type="hidden" size="45" name="value" id="value" value=""><!-- this must be type hidden to support \n in the value -->
<input type="text" size="45" name="changedcomponentid" id="changedcomponentid" title="changed component id"><br>
<input type="text" size="45" name="vischangedcomponentvalue" id="vischangedcomponentvalue" title="changed component value"><br>
<input type="hidden" name="changedcomponentvalue" value="">
<input type="text" size="45" name="currentfocus" id="currentfocus" title="focus id"><br>
<input name="scrollleftpos" id="scrollleftpos" size="45" title="Scroll Left"><br>
<input name="scrolltoppos" id="scrolltoppos" size="45" title="Scroll Top"><br>
<input type="text" size="45" name="uisessionid" id="uisessionid" value="4770" class="fld_ro" readonly="readonly" title="ui session id"><br>
<input type="text" size="45" name="csrftokenholder" id="csrftokenholder" value="ocvdjoiuq2ht8detn26pkjeekg" title="CSRF Token" readonly="readonly" class="fld_ro"><br>
</form>
thanks!!!

How do you get the input text value when click the save button? I have created a sample using the following code, it works well on my side. Please refer to it.
IE.Document.getelementbyid("mx7125[R:0]").Value = "Good"
And web page resource as below (using javascript script get the value document.getElementById('mx7125[R:0]').value):
<div>
<input aria-labelledby="" id="mx7125[R:0]" class="fld text tt" ctype="textbox" li="mx7126[R:0]"
db="mx5134" maxlength="200" style="width:300px;" ontr='true' async='1' ae="setvalue" type="text"
title="Remark: 11_now_test" value="11_now_test" ov="11_now_test" work="1" fldInfo='{"length":"200","inttype":"0"}' />
</div>
<div aria-live="polite" id="mx7126[R:0]_holder" class="bc">
<img sf="1" aria-hidden="true" active="0" ctype="image" alt="" src="../webclient/skins/skins-20171010-1330/tivoli09/images/blank.gif" source="blank" imgtype=".gif"
style="display:inline;margin:0px;" border="0" lc="mx7125[R:0]" align="absmiddle" width='0px' height='26px' id="mx7126[R:0]" title="" /></div>
<input id="btnSubmit" type="button" value="Submit" onclick="Javascript: alert(document.getElementById('mx7125[R:0]').value);" />
If still not working, please post the related code about the save button.

I'am sure there are events to the input fields. Like onChange(), onFocus(), onBlur() and/ or others. You can find out it if you press F12 on the tab with the opened page. Track through the tree of the DOM Inspector. In the row with your code snippet will be a button with the caption "event" at end of line. With a click on the button you can see which events there are.
In the past it was possible to trigger an event with fireEvent(). Another way is dispatchEvent() with some other methods like initEvent().
The words between [] are "outdated" ;-)
[What ever I tryed in the past, nothing worked. So I can't tell how you can solve your problem but I' am sure it is an event problem.]
This link shows you how it should work:
Vba, HTMLSelect: FireEvent OnChange or DispatchEvent
The words between [[]] are not relevant for IE11
[[Another more modern way is *addEventListener()*. But I don't know with which method the IE11 is working:
EventTarget.addEventListener()
The problem for me with *addEventListener()* is, the IE has not eventTarget() Constructer (see browser compatibility table at the bottom of the page):
EventTarget()]]
Edit 1:
In IE11 it works with dispatchEvent() and the other relevant things. You must place all commands in an own method. Two examples:
For onChange() use:
Private Sub Event_onChange(htmlDocument As Object, htmlElementWithEvent As Object)
Dim Event_onChange As Object
htmlElementWithEvent.Focus
Set Event_onChange = htmlDocument.createEvent("HTMLEvents")
Event_onChange.initEvent "change", True, False
htmlElementWithEvent.dispatchEvent Event_onChange
End Sub
For onKeyDown() use :
Private Sub Event_onKeyDown(htmlDocument As Object, htmlElementWithEvent As Object)
Dim Event_onKeyDown As Object
htmlElementWithEvent.Focus
Set Event_onKeyDown = htmlDocument.createEvent("HTMLEvents")
Event_onKeyDown.initEvent "onkeydown", True, False
htmlElementWithEvent.dispatchEvent Event_onKeyDown
End Sub
I know that now because we disscuss this right now in a german forum. The solution with the own sub() is from the user Anton (not involved in the discussion). With Antons sub() I figure out right now how the German Post will let a macro insert adresses in an order blank.
The german discussion:
Webformular (DHL) ausfüllen
Or after one week in the archive:
Webformular (DHL) ausfüllen (archive thread)
Edit 2:
I think you must trigger the onKeyDown event. Try the following:
Dim nodeInput As Object
Set nodeInput = ie.Document.getelementbyid("mx7125[R:0]")
Call TriggerEvent(ie.Document, nodeInput, "onKeyDown")
nodeInput.Value = "Good"
Here is the function to trigger an event like QHarr wrote in the comments with the event type as third function parameter:
Private Sub TriggerEvent(htmlDocument As Object, htmlElementWithEvent As Object, eventType As String)
Dim theEvent As Object
htmlElementWithEvent.Focus
Set theEvent = htmlDocument.createEvent("HTMLEvents")
theEvent.initEvent eventType, True, False
htmlElementWithEvent.dispatchEvent theEvent
End Sub
In the above linked german forum the Deutsche Post form works now with this function. But it is necessary to put in all values two times.
We don't know anything about your page. The url seems to be a secret. If you need more help we need more infos.

Related

Using livewire defer, if input value has text the value is sent when pagination link is clicked- how to stop this?

I'm using livewire with pagination. I set the input to defer so that the search is not carried out until the search button is clicked. However, I have also noticed that if I have any text in the search box that value is sent whenever a pagination button is clicked. I've tried setting the value to "" in jquery $(document).on("click", ".page-link", () => $( "#inlineFormInput" ).val("")); when a pagination buttton is click but that has not solved the problem. And actually clearing the value could cause other problems.
The desired result is that, if for some reason a user leaves text in the searchbox that value is not passed if the user changes their mind and just clicks a pagination link. The input value should only be passed when the search button is clicked. Any help would be greatly appreciated.
livewire component html:
<div id="searchBoxRow">
<input wire:model.defer="search" wire:keydown.enter="updateFaculty" id="inlineFormInput" class="form-control" val="" type="search" autocomplete="off" placeholder="Seach for Name or Country" aria-label="Search">
<button wire:click="updateFaculty" class="btn btn-primary" id="facultyCardsSearchButton" type="submit">
<i class="bi bi-search button-icon"></i>
<span class="button-text">Search</span>
</button>
</div>
livewire php file:
<?php
namespace App\Http\Livewire;
use App\Models\Tag;
use App\Models\Faculty;
use Livewire\Component;
use Livewire\WithPagination;
class FacultyData extends Component
{
use WithPagination;
protected $paginationTheme = 'bootstrap';
public $search = null;
public $tagId = null;
public function updateFaculty(){
$search = $this->search;
$tagId = $this->tagId;
$this->emit('closeAutocomplete');
}
public function updatingSearch()
{
$this->resetPage();
}
public function render()
{
$tags = Tag::all();
$allFaculty = Faculty::searchFilter([$this->search, $this->tagId])->with('country', 'tags')->paginate(10);
return view('livewire.faculty-data', [
'allFaculty' => $allFaculty,
'tags' => $tags
]);
}
}
Here is an idea. You can use the updatingPage() of the $page property hook. When performing the page switch clean the search property. But, somehow you need to check if this is a result of a searched data before or just the client has had his way...well, my idea is get a flagged property to tell livewire what to do. For example
public $searchFlag = false;
public function updateFaculty(){
if ($this->search) // only of search has any value
$this->searchFlag = true;
// do
}
public function updatingPage()
{
if (! $this->searchFlag) {
$this->reset(['search']);
}
if (! $this->search) {
$this->reset(['searchFlag']);
}
}

State is not upating in renderer() component

I'm very new to react JS, and I am using it to build a app now. I have a question.
In of of the Button Click event i have a code logic like this:
handlestartbutton(event) {
const accesskey = localStorage.getItem(localStorageKeys.accessTokenKey);
const decodedAccessKey = jwt_decode(accesskey);
const date = dateConverter.epochToReadableDate(decodedAccessKey.exp);
if (date.currentTime < date.expiryDate) {
this.setState({
accesstokenexpirydate: true
}, () => {
if(this.state.accesstokenexpirydate === false) {
//rest of the code
}
})
In renderer() i have a a pop up UI like this:
renderer()
{
{this.state.accesstokenexpirydate === true ? (
<Popup
open ={this.state.open}
closeOnDocumentClick={false}
closeOnEscape={false}
onClose={this.closeModal}className
>
<div className={popstyles.popupBody}>
<div className={popstyles.modalClose}>
<a className="close" onClick={this.closeModal}>
×
</a>
{""}
<div className ={popstyles.unAutherizedUser}>
<label >{homeConstantMessages.accessTokenExpire}</label>
<div className ={popstyles.unAutherizedUserMsg}>
<label>{homeConstantMessages.accessTokenExpireMsg}</label>
<button className ={styles.refreshaccessbtn} onClick = {this.navigateToHomePage.bind(this)} label = {homeConstantMessages.refreshbtn}>
</button>
</div>
</div>
</div>
</div>
</Popup>
) : (
''
)}
}
The problem is when the first time start button is clicked this pop up UI is not getting popped even though the state variable accesstokenexpirydate is set to true. when second time the button is cicked UI is popping up. can anyone please help me out here
1) I think you have to apply arrow function like follows and then you can use this
handlestartbutton=(event)=> {...}
2) I'm quite confused about the name, don't you think it should be render(...) instead of renderer()

validating bootstrap datepicker using Qunit

I have a bootstrap calendar on my page that lets the user pick a date. I have a start time and endtime. I would like to test to do the following.
If the user leaves the date selector empty, the test will fail with a message like cannot leave fields empty.
If the user enters an endtime that is less than the startime the test will fail and throw a message like Cannot have endtime less than starttime.
I will paste the code that works with the datepicker. I am using Qunit for testing purposes and Bootstrap 4.
button.js
// Runs date picker plugin
$('input.date').datepicker();
// Gets data
var data;
fetch('/reportSaver', {
// data: dates,
method: 'POST'
}).then(function (response) {
return response.json();
}).then(function (json) {
data = json;
});
// Form submit
$('form').on('submit', function (event) {
event.preventDefault();
var dates = {
startdate: new Date($('.startdate').val()),
enddate: new Date($('.enddate').val())
};
// Minimum validation for dates
if ((dates.startdate && dates.startdate > dates.enddate) ||
(dates.enddate && dates.enddate < dates.startdate)) {
return alert('Use valid dates!');
}
// Filter rows
var rows = data.filter(function (register) {
var date = new Date(register.receivedDateTime);
return (
(!dates.startdate || date > dates.startdate) &&
(!dates.enddate || date < dates.enddate)
);
// Convert to HTML
}).map(function (row) {
return `
<tr>
<td> </td>
<td>${row.subject || '-'}</td>
<td>${row.receivedDateTime || '-'}</td>
<td>${row.isRead || '-'}</td>
<td>${row.sendDateTime || '-'}</td>
</tr>
`;
});
// Show content
$('table tbody').html(rows.join(''));
});
// Clear click
$('.clear-table').on('click', function () {
// Clears table
$('table tbody').html('<tr><td colspan="5">Make a search</td></tr>');
// Clears inputs
$('input').val('');
});
form.html
{{!-- Post form for Date Picker --}}
<form id="post_form" method="GET" action="/routes/reportSaver.js">
<div class="date-picker">
<h3>Date</h3>
<input placeholder="Initial date" type="text" class="date startdate"> -
<input placeholder="End date" type="text" class="date enddate">
</div>
<hr>
{{!-- Button to save the Report --}}
<button id="bt1" type="submit" class="btn btn-danger">Click to Get Reports</button>
<button id="bt2" type="submit" class="btn btn-danger clear-table">Clear</button>
</form>
Qunit Test Example
QUnit.test("Datepicker Test", function (assert) {
var datepicker = $("#startDate");
var event = $.Event("onSelect");
datepicker.on("onSelect"),
function () {
alert("Test");
};
// Trigger the key event
datepicker.trigger(event);
});

How to get textbox value in Action in asp.net MVC 5

I want to send the value of textbox to the Action Method for searching the technology for that i want to get the value of textbox in Action.
I have the following code :-
#Html.TextBox("technologyNameBox", "", new { id = "technologyName", #class = "form-control", #placeholder = "Search For Technology" })
<span class="input-group-btn" style="text-align:left">
<a class="btn btn-default" id="searchTechnology"
href="#Url.Action("SearchTechnology", "Technology",
new {technologyName="technologyName",projectId=ProjectId })">
<span class="glyphicon glyphicon-search "></span>
</a>
</span>
Question :- How to get the value of textbox "technologyNameBox" in Action ?
Please help me out. Thanks in Advance!
You'd have to append the value to the URL via JavaScript before directing the user. Using jQuery (since that generally comes packaged with ASP.NET), it might look something like this (with a good bit of manual conditional checks for blank values or query string parameters):
$('#searchTechnology').click(function (e) {
e.preventDefault();
var url = '#Url.Action("SearchTechnology", "Technology", new { projectId=ProjectId })';
var technologyName = $('#technologyName').val();
if (technologyName.length < 1) {
// no value was entered, don't modify the url
window.location.href = url;
} else {
// a value was entered, add it to the url
if (url.indexOf('?') >= 0) {
// this is not the first query string parameter
window.location.href = url + '&technologyName=' + technologyName;
} else {
// this is the first query string parameter
window.location.href = url + '?technologyName=' + technologyName;
}
}
return false;
});
The idea is that when the user clicks that link, you would fetch the value entered in the input and append it to the URL as a query string parameter. Then redirect the user to the new modified URL.

Unobtrusive validation with Jquery Steps Wizard

Recently I asked a question for how to customize the JQuery Steps as I wanted to use partial views instead of static content. I have partially solved that problem by using the following code supported by jquery-steps,
<h3>Step 1</h3>
<section data-mode="async" data-url="/Formation/RenderStep1"></section>
<h3>Step 2</h3>
<section data-mode="async" data-url="/Formation/RenderStep2"></section>
Now the big problem I am facing right now is how to use unobtrusive validation. I don't want to use JQuery custom validation and there must be some way of using Obtrusive with it.
Each partial view that is rendered has its own form. I want to validate the form in the onStepChanging function of jquery-steps,
$("#my-steps").steps({
headerTag: "h3",
bodyTag: "section",
contentMode: "async",
transitionEffect: "fade",
stepsOrientation: "vertical",
onStepChanging: function (event, currentIndex, newIndex) {
return true;
}
});
I have tried calling $.validator.unobtrusvie.parse('#myform'); in the onStepChanging function but ('#myform') is undefined and still I don't know that whether this is the right way to call the unobtrusive validation manually. Kindly guide me and show me the direction to achieve this. Any help will be highly appreciated.
It sounds like your trying manage multiple forms within the JQuery Steps library and I don't think that is what its intended for.
When you configure JQuery Steps, you set it up against the form in your view.
Unobtrusive JQuery Validation is looking at the model in your view and automatically configuring the HTML with the relevant data attributes for error handling.
This validation should be firing at the client side automatically.
There shouldn't be a problem with using Partial View's, as long as there encapsulated within the same form element.
What is the requirement to have each partial view wrapped in its own form? If your trying to make multiple posts throughout the JQuery Steps form wizard, your defeating the object.
At each step in the JQuery Steps form, your only validating the one form like this :-
onStepChanging: function (event, currentIndex, newIndex) {
//Allways allow user to move backwards.
if (currentIndex > newIndex) {
return true;
}
// Remove the validation errors from the next step, incase user has previously visited it.
var form = $(this);
if (currentIndex < newIndex) {
// remove error styles
$(".body:eq(" + newIndex + ") label.error", form).remove();
$(".body:eq(" + newIndex + ") .error", form).removeClass("error");
}
//disable validation on fields that are disabled or hidden.
form.validate().settings.ignore = ":disabled,:hidden";
return form.valid();
}
Once the user has finished entering data, and the client side validation has been met, you hook into the onFinished method and post the form :-
onFinished: function (event, currentIndex) {
var form = $(this);
form.submit();
}
The purpose of JQuery Steps is to allow the user to have a fluid experience of filling out a form and to not be overwhelmed with the number of questions been asked.
From the developers perspective, it enables us to split up the form into nice size-able chunks without having to worry about saving progress between screens or losing the state of the form data and allows us to capture all of the required data with only having to make that one post once all validation criteria has been met.
I tried the formvalidation plugin, it will relax your mind from searching in validation without form tag or validation without submit the form that's the issue I solved when I tried it.
I know it's not free but you can try it from here, personally I like it
First update height after validation
<style type="text/css">
/* Adjust the height of section */
#profileForm .content {
min-height: 100px;
}
#profileForm .content > .body {
width: 100%;
height: auto;
padding: 15px;
position: relative;
}
Second, add data-steps index to your section*
<form id="profileForm" method="post" class="form-horizontal">
<h2>Account</h2>
<section data-step="0">
<div class="form-group">
<label class="col-xs-3 control-label">Username</label>
<div class="col-xs-5">
<input type="text" class="form-control" name="username" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Email</label>
<div class="col-xs-5">
<input type="text" class="form-control" name="email" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Password</label>
<div class="col-xs-5">
<input type="password" class="form-control" name="password" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Retype password</label>
<div class="col-xs-5">
<input type="password" class="form-control" name="confirmPassword" />
</div>
</div>
</section>
Third, javascript code
<script>
## // to adjust step height to fit frame after showing validation messages##
$(document).ready(function() {
function adjustIframeHeight() {
var $body = $('body'),
$iframe = $body.data('iframe.fv');
if ($iframe) {
// Adjust the height of iframe
$iframe.height($body.height());
}
}
// IMPORTANT: You must call .steps() before calling .formValidation()
$('#profileForm')
// setps setup
.steps({
headerTag: 'h2',
bodyTag: 'section',
onStepChanged: function(e, currentIndex, priorIndex) {
// You don't need to care about it
// It is for the specific demo
adjustIframeHeight();
},
// Triggered when clicking the Previous/Next buttons
// to apply validation to your section
onStepChanging: function(e, currentIndex, newIndex) {
var fv = $('#profileForm').data('formValidation'), // FormValidation instance
// The current step container
$container = $('#profileForm').find('section[data-step="' + currentIndex +'"]');
// Validate the container
fv.validateContainer($container);
var isValidStep = fv.isValidContainer($container);
if (isValidStep === false || isValidStep === null) {
// Do not jump to the next step
return false;
}
return true;
},
// Triggered when clicking the Finish button
onFinishing: function(e, currentIndex) {
var fv = $('#profileForm').data('formValidation'),
$container = $('#profileForm').find('section[data-step="' + currentIndex +'"]');
// Validate the last step container
fv.validateContainer($container);
var isValidStep = fv.isValidContainer($container);
if (isValidStep === false || isValidStep === null) {
return false;
}
return true;
},
onFinished: function(e, currentIndex) {
// Uncomment the following line to submit the form using the defaultSubmit() method
// $('#profileForm').formValidation('defaultSubmit');
// For testing purpose
$('#welcomeModal').modal();
}
})
.formValidation({
framework: 'bootstrap',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
// This option will not ignore invisible fields which belong to inactive panels
excluded: ':disabled',
fields: {
username: {
validators: {
notEmpty: {
// for asp.net i used element attribute to integerated with unobtrusive validation
// message :$('username').attr('data-val-required')
message: 'The username is required'
},
stringLength: {
min: 6,
max: 30,
message: 'The username must be more than 6 and less than 30 characters long'
},
regexp: {
regexp: /^[a-zA-Z0-9_\.]+$/,
message: 'The username can only consist of alphabetical, number, dot and underscore'
}
}
},
email: {
validators: {
notEmpty: {
message: 'The email address is required'
},
emailAddress: {
message: 'The input is not a valid email address'
}
}
},
password: {
validators: {
notEmpty: {
message: 'The password is required'
},
different: {
field: 'username',
message: 'The password cannot be the same as username'
}
}
},
confirmPassword: {
validators: {
notEmpty: {
message: 'The confirm password is required'
},
identical: {
field: 'password',
message: 'The confirm password must be the same as original one'
}
}
}
}
});

Resources