in cf9 i have a page where i want to check if field value exist in db (via ajax). If it doesn't exist, i want to stop processing (return false). Everything works fine, except i don't know how to pass back to the main function the result of the ajax call
please help
<cfajaximport tags="cfmessagebox, cfwindow, cfajaxproxy">
<cfajaxproxy cfc="reqfunc" jsclassname="jsobj" />
<script language="JavaScript">
function checkRequired() {
var testVal = document.getElementById('myField').value;
return testAjax(testVal);
/* more processing that should stop if ajaxCallBack returns false */
}
function testAjax(testVal) {
var instance = new jsobj();
instance.setCallbackHandler(ajaxCallBack);
instance.checkProfile(testVal);
}
function ajaxCallBack(returns) {
alert(returns);
// returns correctly "true" if value checks against db, "false" if it doesn't
// HOW DO I PASS THIS VALUE BACK TO checkRequired ???
}
</script>
<form>
<input type="text" name="myField" id="myField" value=""><p>
<input type="button" value="Check with Ajax" onClick="return checkRequired()">
</form>
many thanks
Unless you build your main function to 'wait' for the return, you can't return your result to that instance of the function; it has already exited, so to speak. Using cfajax it is probably possible to tweak the main function to call and wait, but the simple solution is to have the callback subsequently recall your main function and treat the existence of the result/return as the flag as to whether to process or call the ajax.
function checkRequired(return) {
if(return != null) {
/* more processing */
} else {
testAjax(testVal);
}
}
function ajaxCB(return) {
checkRequired(return);
}
I would probably refactor a bit more but you should get the idea.
it's really kind of a hack, not what i was looking for, but for what it's worth: if i put this stanza at the very end of my function, with the callBack collapsed within the main function, it would work
function checkRequired() {
var testVal = document.getElementById('myField').value;
var instance = new jsobj();
var r = instance.setCallbackHandler(
function(returns) {
if(returns == 1) {
document.getElementById('testForm').submit();
} else { alert("Something wrong"); }
}
);
instance.checkProfile(testVal);
}
Related
I have using the template code like:
{snippetArea wrapper}
{control addFormControl}
{/snippetArea}
and in addFormControl component code is like:
{snippet clientSnippet}
......
{/snippet}
I am using ajax with method presenter method:
public function handleClientChange(){
$this['addFormControl']['addForm']['consignment_client']->setValue("test");
$this->redrawControl('wrapper');
$this->redrawControl('clientSnippet');
}
But it is not redraw the snippet snippet id is snippet-addFormControl-clientSnippet. Please help me to fix it.
I dont think you can call $this->redrawControl('clientSnippet'); in presenter and expect to redraw component. You should call this in the component.
Something like $this['addFormControl']->redrawControl('clientSnippet');
this is how you can do it.
In my latest project i was doing something quite similiar, it's pretty simple tho.
For Nette I use this Ajax: https://github.com/vojtech-dobes/nette.ajax.js
.latte file:
<input type="text" id="search-car" data-url="{plink refreshCars!}">
{snippet carlist}
{foreach $cars as $car}
{var $photo = $car->related('image')->fetch()}
{if $photo}
<img src="{plink Image:image $photo->filename}"/>
{/if}
</a>
{/foreach}
{/snippet}
Notice the '!' at the end of the text input. It's tells Nette to look after the handle function.
The presenter:
public function handleRefreshCars()
{
$this->redrawControl('carlist');
}
public function renderDefault($foo = null)
{
if ($foo === null || $foo === '') {
$this->template->cars = array();
} else {
$this->template->cars = $this->carDao->getFiltered($foo);
}
}
And JS:
function callFilterAjax(url, data) {
$.nette.ajax({
url: url,
data: data
});
}
$("#search-contract-car").on('load focus focusout change paste keyup', function () {
callFilterAjax($(this).data('url'), {"foo": $(this).val()});
});
This should be it. I hope you find this useful
I want the view to always be updated with the result of the latest call to searchWiki(). I've used a module that resolves repeated calls to $.ajax to the value returned by the most recent call.
It still seems to go out of sync and show the result of previous calls however. I'm guessing this is because setState is async? How should I keep the two async operations in sync?
In addition, I realize I should put in a debounce somewhere, but I'm not sure what I should debounce. handleChange, searchWiki or latestAjax?
Here is a demo: http://codepen.io/prashcr/pen/obXvWv
Try typing stuff then backspacing to see what I mean.
Search component
<div style={style}>
<input
value={this.props.search}
// this calls searchWiki with e.target.value
onInput={this.handleChange}
/>
</div>
searchWiki function of parent component
searchWiki (search) {
console.log('searchWiki called with: ' + search);
if (!search) {
this.setState({results: []});
}
else {
// "latest" taken from https://github.com/bjoerge/promise-latest
let latestAjax = latest($.ajax);
let options = {
url: this.props.url + search,
dataType: 'jsonp'
};
latestAjax(options)
.then(data => {
var results = data.query.search.map(res => {
res.url = 'http://en.wikipedia.org/wiki/' + encodeURIComponent(res.title);
return res;
});
this.setState({results: results});
})
.error(e => console.log(e.message));
}
}
The handleChange function is too generic to be debounced with a hardcoded value as you might want to use this search component elsewhere. However, you still want to catch the repeating action as early as possible and ensure that it never does any unnecessary work.
Therefore I would suggest that you debounce the handleChange function with an optional prop, defaulting to 0ms.
getDefaultProps() {
return {
debounce: 0
};
},
render() {
// ...
return (
<div style={style}>
<input
// ...
onInput={debounce(this.handleChange, this.props.debounce)}/>
</div>
);
}
Then make sure you pass this prop whenever you want to debounce the handler.
<Search onSearch={this.searchWiki} debounce={1000} />
Your other problem is happening because you are calling latest inside your searchWiki function and you only call the returned function once! Each time you call searchWiki you create a new latestAjax function.
For it to work, you'll need to call the returned function multiple times.
This means defining the wrapped $.ajax function outside of searchWiki function.
latestAjax: latest($.ajax),
searchWiki(search) {
// ...
this.latestAjax(options)
.then(data => {
});
}
I've created validation rules for image uploading as follows.
$this->form_validation->set_rules('display_photo', 'Display Photo', 'callback_file_required|callback_file_size_max[1000]');
In controller I've included callback function as follows.
public function file_required($display_photo) {
if($_FILES[$display_photo]['size'] == 0) {
$this->form_validation->set_message('file_required', 'Upload a file.');
return false;
}
return true;
}
public function file_size_max($display_photo, $max_size) {
if($_FILES[$display_photo]['size'] > $max_size) {
$this->form_validation->set_message('file_size_max', 'This file exceeds max size.');
return false;
}
return true;
}
Only first rule is executing but not second rule. Please help me to find out the solution.
You should pass the file size limit in the config not in the validation rule.
Can u please paste the function or method that performs the upload ?
Not sure if you can use two callbacks on a single field when validation forms in CI. In any case you don't need to check the size to see if a file was uploaded. Use error code '4'
Solutions:
Check if the file was uploaded with if($_FILES[$display_photo]['error'] !== 4) // Error code 4 means no file was uploaded. So if it's not 4 then you have a file.
If you want to do multiple checks you can put them both in one single callback
$this->form_validation->set_rules('display_photo', 'Display Photo', 'callback_file_required_with_validation');
public function file_required_with_validation($display_photo) {
$max_size=1000;
if($_FILES[$display_photo]['size'] == 0) {
$this->form_validation->set_message('file_required', 'Upload a file.');
return false;
}
if($_FILES[$display_photo]['size'] > $max_size) {
$this->form_validation->set_message('file_size_max', 'This file exceeds max size.');
return false;
}
return true;
}
Pretty sure you need double underscore after 'callback' in your validation definition...
$this->form_validation->set_rules('display_photo', 'Display Photo', 'callback__file_required|callback__file_size_max[1000]');
One way - You can validate with JS before uploading the file:
<form method="post" enctype="multipart/form-data" action="upload.php">
<input type="file" name="file" id="file" />
<input type="submit" name="submit" value="Submit" />
</form>
<script>
document.forms[0].addEventListener('submit', function( evt ) {
var file = document.getElementById('file').files[0];
if(file && file.size < 10485760) { // 10 MB (this size is in bytes)
//Submit form
} else {
//Prevent default and display error
evt.preventDefault();
}
}, false);
</script>
Original Question is here
But if you want validate at server side, then server until does't know whenever we upload the file.
I'm trying to Validate my form before it's being sent to the server. I tried couple of J/S plugins for regular validation and none of them seem to work.
I tried looking for getJSON validation method with jquerymobile but haven't seen anything related. Is using $.getJSON the right approach?
Here is a fiddle http://jsfiddle.net/Kimbley/kMsXK/2/
Thanks :D
Code Here:
function mAddBusiness() {
$.getJSON("API.php", {
command: "addBusiness",
bsnName: $("#mBsnName").attr("value"),
bsnCity: $("#mBsnCity").attr("value"),
bsnAddress: $("#mBsnAddress").attr("value"),
bsnMenu: $("#mBsnMenu").attr("value"),
bsnLat: bsnLat,
bsnLong: bsnLong
},
function () {
$("#mBsnName").attr("value", "");
$("#mBsnCity").attr("value", "");
$("#mBsnAddress").attr("value", "");
$("#mBsnMenu").attr("value", "");
alert("Business was added successfully ");
}
);
}
Inside your mAddBusiness() function you can just do your validation before sending the AJAX request. Something like:
function mAddBusiness() {
if ($("#mBsnName").val() !== '') {
$.getJSON("API.php", {
command: "addBusiness",
bsnName: $("#mBsnName").val(),
bsnCity: $("#mBsnCity").val(),
bsnAddress: $("#mBsnAddress").val(),
bsnMenu: $("#mBsnMenu").val(),
bsnLat: bsnLat,
bsnLong: bsnLong
},
function () {
$("#mBsnName").val("");
$("#mBsnCity").val("");
$("#mBsnAddress").val("");
$("#mBsnMenu").val("");
alert("Business was added successfully ");
}
);
} else {
alert('Please enter a business name.');
}
}
Note that you will have to add the data-ajax="false" attribute to the <form> tag in question so that jQuery Mobile does not attempt to submit the form itself.
Also, note that $('input').attr('value') will not return the current value of an input, it will return the initial value before the user had a chance to input anything. To get the current value of a form input, use .val(): http://api.jquery.com/val
I am having one small problem with my code. I am sending a POST request to my page, after I am done it should return "OK" meaning it worked. From inside my handler function I call set_var(data) to set my global variables text, but the problem is my print_info() returns undefined.
I've spent a lot of time on this and realize my problem has to do with scoping somehow but I am not sure how to go about fixing it. If anyone can provide any pointers, that would be great.
<?
if($_REQUEST['action'] == 'test')
{
echo "OK";
die;
}
?>
<script type="text/javascript" src="jquery-1.6.1.js" ></script>
<script type="text/javascript">
var ajax_post_result;
function set_var(data)
{
//PRINTS MY TEXT OK
alert("SET:: " + data);
//SET TO MY GLOBAL VARIABLE
ajax_post_result = data;
//ALSO PRINTS OK
alert("SET2:: " + ajax_post_result);
}
function return_handler(data, textStatus)
{
//THESE BOTH WORK ... BUT ONLY HERE AND WITHIN set_var()
//alert("1: " + data); //PRINTS WHAT I NEED
//CALL FUNCTION TO SET GLOBAL VARIABLE
set_var(data);
}
function print_info()
{
return ajax_post_result;
}
function ajax_post(file, data )
{
$.post( file, data, return_handler);
//PRINTS UNDEFINED
alert("RETURN:: " + print_info() );
}
</script>
<form id=newform name='testform'>
<input type="hidden" name="newexample" value="1">
Enter Something: <input name="something" id='something1' value="" type="text">
<input type="button" value="Submit" name="Submit" onclick="ajax_post('index.php?action=test', $('#newform').serialize() ); return false;">
</form>
AJAX requests are, as evidenced by the first A in the acronym, asynchronous. So, when you call $.post(), execution of the ajax_post function continues on its merry way more or less immediately, without waiting for the request to finish. You get to your "RETURN" alert before your return_handler has run to set the global variable.
You can use jQuery.ajax and set the async option to false, which will get you a synchronous request.
Or, and I recommend this strategy, move all the things that need to happen only after the request is done to the success handler.
Your problem is due to the asynchronous nature of AJAX.
You should do all your post AJAX processing in the callback function. Something like this (using your current functions)
$.post(file, data, function(data, textstatus) {
return_handler(data, textstatus);
alert("RETURN:: " + print_info());
});
Though you could easily combine your functions into the one closure (minus the alerts), eg
$.post(file, data, function(data, textstatus) {
ajax_post_result = data;
});