I have been working on a code to autofill dropdowns onchange, after selecting the required values from an autocomplete search field. The problem is that my autofill does not work after selecting the value, but the Jquery to execute the script and fetch the id works perfectly, don’t know what I’m missing. here’s a bit of my code and picture. Take note I have multiple jquery scripts executing types of programs. Here is the error message I get
Message: Could not find row 50390
Stack trace:
C:\xampp\htdocs\portal-gep-2\application\modules\admin\controllers\AjaxController.php(366): Model_SicCode->getsiccode('50390'
Request Parameters:
array (
'controller' => 'ajax',
'action' => 'autofill',
'sicid' => '50390',
'lang' => 'en',
'module' => 'admin',
)
The id does exist in my database but my dropdowns just don’t change. How can I go about this?
contoller
public function autofillAction()
{
//get the id send via a get - the sic id
$division= $this->getRequest()->getParam('sicid');
//get majorgroup name, group name and sic description
//fill dropdowns with relevant values - new form with drop downs
//selecting the required values same as autocomplete (don't know)
$mdlSic = new Model_SicCode();
$results = $mdlSic->getsiccode($division);
foreach($results as $result)
{
$Division = $result->div_code;
$mdlDivision = new Model_Division();
$result = $mdlDivision->getSicViaDiv($division);
$name = $result->div_desc;
$id = $result->div_code;
$mgrp_desc->addMultiOption($id, $name);
}
$mgrp_desc->setOrder(4);
$this->_helper->viewRenderer->setNoRender(false);
$this->_helper->layout->disableLayout();
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('newfield', 'html')->initContext();
$id = $this->_getParam('id', null);
$this->view->field = $div_desc->__toString();
}
jquery
function ajaxautofill(id) {
$.ajax({
type: 'POST',
datatype: 'JSON',
url: '<?php echo $this->baseURL()?>/admin/ajax/autofill/sicid/' + id,
//data: 'division':$('#div_desc').val(),
//dataType: 'JSON',
//async: true,
success: function(data)
{
//fill drop downs
$('#t2').append(data);
}
});
}
Get siccode
public function getSICviaDiv($d_id)
{
$select = $this->select()->where('div_code = ?', $d_id);
$results = $this->fetchAll($select);
if (count($results))
return $results;
else
return 'nothing';
}
GetsicViaDiv
public function getSicViaDiv($siccode)
{
$select = $this->select();
$select->where('div_code = ?', $siccode);
return $this->fetchAll($select);
}
Firstly, you've built the select object twice. Secondly, I'd suggest the answer is here:
$row = $this->fetchRow($select);
if (!$row)
{
throw new Exception("Could not find row $id");
}
You're throwing an exception if the RowSet object returned, from fetchRow, is false. I'll work up some code this evening when I have my laptop handy.
Related
I have a country, state and city chained dropdown which loads a state depending on the country and loads the cities depending on the state. The code works perfectly fine on my local server but when pushing to the live one, the dropdown is not functioning correctly, for example in some cases it works fine for all 3 but for some cases it just does not load anything and in the console I am seeing a simple false and nothing else.
Here is the JS:
$(document).ready(function() {
var country_id = localStorage.getItem("select2CountryValue");
var state_id = localStorage.getItem("select2StateValue");
var page_load = true; //added this
// Triggering the deleteLocalStorage function in case the client is not
// created and the back button is clicked
$('.del-ls').click(function() {
deleteLocalStorage();
});
// This function is also called by PHP using script tags when the create
// client form is successfully submitted
function deleteLocalStorage() {
var country_id = localStorage.getItem("select2CountryValue");
var state_id = localStorage.getItem("select2StateValue");
localStorage.removeItem('select2CountryValue');
localStorage.removeItem('select2StateValue');
}
//$('.csc-select').select2();
$('#country').select2({
placeholder: 'Select Country'
});
$('#state').select2({
placeholder: 'Select State/Region'
});
$('#city').select2({
placeholder: 'Select City'
});
$('select[name="country"]').on('change',function() {
var country_id= $(this).val();
localStorage.setItem("select2CountryValue", country_id);
if (country_id) {
$.ajax({
url: "/src/Pages/world/getStates.php",
type: "GET",
data: {'country_id':country_id},
dataType: "json",
success: function(data) {
console.log(data);
$('select[name="state"]').empty();
$('select[name="state"]').append('<option value="">Select State</option>');
$.each(JSON.parse(data), function(key,value) {
$('select[name="state"]').append('<option value="'+value.id+'">'+value.name+'</option>');
});
//check if the change is called on page load
if (page_load == true) {
$('#state').val(state_id).trigger('change'); //assign slected value after element option is added in dom
page_load = false; //adding this so that next time this doesn't get execute
}
}
});
} else {
$('select[name="state"]').empty();
}
});
$('#country').val(country_id).trigger('change');
$('select[name="state"]').on('change',function() {
var country_id = $('#country').val();
var state_id = $(this).val();
localStorage.setItem("select2StateValue", state_id);
if (state_id) {
$.ajax({
url: "/src/Pages/world/getCities.php",
type: "GET",
data: {'country_id': country_id, 'state_id': state_id},
dataType: "json",
success: function(data) {
console.log(data);
$('select[name="city"]').empty();
$('select[name="city"]').append('<option value="">Select City</option>');
$.each(JSON.parse(data),function(key,value) {
$('select[name="city"]').append('<option value="'+value.id+'">'+value.name+'</option>');
});
}
});
} else {
$('select[name="city"]').empty();
}
});
});
And this is the HTML and just a some simple PHP to load the countries which is working fine:
<p>
<span>Country</span>
<select class="csc-select" name="country" id="country">
<option value="">Select Country</option>
<?php foreach($countries as $country) { ?>
<option value="<?php echo $country[$columnName['COLUMN_NAME']]; ?>"
>
<?php echo $country['name']; ?>
</option>
<?php } ?>
</select>
</p>
<p>
<span>State</span>
<select class="csc-select" name="state" id="state">
<option value="">Select State</option>
</select>
</p>
<p>
<span>City</span>
<select class="csc-select" name="city" id="city">
<option value="">Select City</option>
</select>
</p>
I am a bit clueless now since locally it works perfectly however on the live server it doesn't work for every option you pick, I rechecked the countries, states and cities database and all the info is there so its not missing, the database is identical to the one I am using in the local version too. If anyone has any idea or suggestions, I would appreciate it a lot.
And here is the console log error that appears sometimes:
> Uncaught SyntaxError: Unexpected end of JSON input
> at JSON.parse (<anonymous>)
> at Object.success (add:977:29)
> at c (jquery-3.6.0.min.js:2:28327)
> at Object.fireWith [as resolveWith] (jquery-3.6.0.min.js:2:29072)
> at l (jquery-3.6.0.min.js:2:79901)
> at XMLHttpRequest.<anonymous> (jquery-3.6.0.min.js:2:82355)
and now I am adding a screenshot of the console.log, this happens when I choose the country United States, the state Caliornia, so it does not show anything for California but it should:
Here is the getStates.php file code:
<?php
use App\Session;
use App\Login;
use App\Location;
require_once("../../../vendor/autoload.php");
$objSession = new Session();
if(!$objSession->isLogged()) {
Login::redirectTo("/login");
}
$country_id = $_GET['country_id'];
if(isset($_GET['country_id'])) {
$objLocation = new Location();
echo json_encode($getStates = $objLocation->getStates($country_id));
}
and here is the getCities.php file code:
<?php
use App\Session;
use App\Login;
use App\Location;
require_once("../../../vendor/autoload.php");
$objSession = new Session();
if(!$objSession->isLogged()) {
Login::redirectTo("/login");
}
$state_id = $_GET['state_id'];
$country_id = $_GET['country_id'];
if(isset($_GET['state_id']) && isset($_GET['country_id'])) {
$objLocation = new Location();
echo json_encode($getCities = $objLocation->getCities($state_id, $country_id));
}
and this is the code in the Location class that fetches the data:
public function getStates(string $id): ?string
{
$sql = "SELECT `id`, `name` FROM {$this->table_3}
WHERE `country_id` = '". $this->escape($id) ."'
ORDER BY `name` ASC";
$result = $this->fetchAll($sql);
return json_encode($result);
}
public function getCities(string $state, string $country): bool|string
{
$sql = "SELECT `id`, `name` FROM {$this->table_4}
WHERE `state_id` = '". $this->escape($state) ."'
AND `country_id` = '". $this->escape($country) ."'
ORDER BY `name` ASC";
$result = $this->fetchAll($sql);
return json_encode($result);
}
So, I have asked on the comments and you have provided... here is what I think is happening... and what I think you should do.
your method getCities on the Location::class is returning a boolean... and sometimes a string...
json_encode will only return false on failure, this means json_encode has failed on encoding your sql result...
you can use json_last_error() and json_last_error_msg() to debug your json_encode() problem
you can find the documentation here
You can debug your problem on Local but, please make sure your local machine is running the same things on the live server, to replicate the error...
PHP version
Database Data
MySql Version (But I don't think it's necessary)
Browser (but just for testing, app should work on all browser)
if you can't replicate the error, you need to do it LIVE. (please be very careful, this should be your LAST RESORT)
I could not provide a specific answer because I don't know if $this->fetchAll() only returns an array or maybe sometimes it returns an error message...
I have provided you this answer, because your main concern on this question is why your program returning a simple false value...
for example in some cases it works fine for all 3 but for some cases it just does not load anything and in the console I am seeing a simple false and nothing else.
Hi I think it could be the $.ajax AND the echo json_decode the issue....
I made my own AJAX function that I share in github https://github.com/jintor/stubajax
async function stubajax (divid,phphat,postix = [],pend = 'html') {
var pcache = (Math.floor(Math.random() * 100000000) + 1);
postix["preventcache"] = pcache; // prevent browser caching
postix["divid"] = encodeURIComponent(divid);
postix["mojax_height"] = encodeURIComponent($(window).height());
postix["mojax_width"] = encodeURIComponent($(window).width());
// if you need to send cookies
postix["cookies"] = decodeURIComponent(document.cookie);
// if you need to send localStorage or sessionStorage stuff
for (var i = 0; i < localStorage.length; i++){ postix[localStorage.key(i)] = localStorage.getItem(localStorage.key(i)); }
for (var i = 0; i < sessionStorage.length; i++){ postix[sessionStorage.key(i)] = sessionStorage.getItem(sessionStorage.key(i)); }
await fetch(phphat+"?pcache="+pcache, {
method: "POST", body: JSON.stringify(Object.assign({}, postix)), headers: {"Content-type": "application/json; charset=UTF-8"}
}).then( response => { return response.text(); }).then( html => {
switch ( pend ){
case 'append' : $("#"+divid).append(html); break;
case 'prepend' : $("#"+divid).prepend(html); break;
default : $("#"+divid).html(html); break;
}
}).catch( err => console.log(err) );
}
AND YOU USE IT LIKE THIS
<input onchange="stubajax (\'div_id_that_will_reseive_the_ajax_message\',\'/path/to_php.php\',{\'extra1\':this.value},'html');
On the PHP side :
a the end simply echo (WITHOUT json_encode)....
So I am adding the solution which #SeanReyes led me to.
Actually it led me to 2 solutions, and they are:
Solution 1. I could simply do an if condition in my Location::class to check if the json_encode is working correctly and if not simply add a JSON flag like so (JSON_INVALID_UTF8_IGNORE or JSON_INVALID_UTF8_SUBSTITUTE):
public function getStates(string $id): ?string
{
$sql = "SELECT `id`, `name` FROM {$this->table_3}
WHERE `country_id` = '". $this->escape($id) ."'
ORDER BY `name` ASC";
$result = $this->fetchAll($sql);
if(json_encode($result)) {
return json_encode($result);
} else {
return json_encode($result, JSON_INVALID_UTF8_IGNORE);
}
}
and did the same with the getCities method.
Solution 2. While this did fix it, it displayed the latin characters incorrectly and so that made me find another easy solution by simply adding a charset to my mysqli connection like so:
$this->db->set_charset("utf8mb4");
and like magic everything worked perfectly, but this was a rookie mistake on my end as this should of been set anyway, thanks to everyone for pointing me in the right direction.
i have implemented live search with jquery typeahead library, it is working fine for the case of data being received from database i have the issue on front end
right now the typeahead is working fine for displaying data what i want to do is add url in the href attribute of the li'sbeing generated from the dropdown but i havent still been able to even attach an onclick method with the li's here's my code so far.
HTML
<input autocomplete="off" id="type" placeholder="Search for product / category"/>
JAVASCRIPT
$('#type').typeahead({
source: function (query, result) {
$.ajax({
url: "<?php echo base_url()?>ajax_search/search2",
data: 'query=' + query,
dataType: "json",
type: "POST",
success: function (data) {
result($.map(data, function (item) {
return item;
}));
}
});
}
});
PHP CI Model Function
public function search($query){
$keyword = strval($query);
$search_param = "{$keyword}%";
$conn =new mysqli($this->db->hostname, $this->db->username, $this->db->password , $this->db->database);
$countryResult[]=array();
$sql = $conn->prepare("SELECT * FROM category WHERE name LIKE ?");
$sql->bind_param("s",$search_param);
$sql->execute();
$result = $sql->get_result();
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$countryResult[] = $row["name"];
}
echo json_encode($countryResult);
}
}
this is the html structure that is being generated when typeahead is called
this is what i have tried so far!
$(".typeahead").on( "click", "li", function() {
alert("1");
});
$(".typeahead .dropdown-item").delegate("click", function(){
alert("12");
});
$(".typeahead .dropdown-item").on("click", function(){
alert("123");
});
i copied one of the code from this thread stackoverflow thread but it is still not working for my case i have not idea why it is not working any help?
Since the element you are attaching the click event to will have been added to the DOM dynamically by typehead, you'll want to do so like this:
$('body').on('click', '.typeahead .dropdown-item', function() {
// do something
});
I'm new to stackoverflow (as a member at least) and I have a question.
I'm also new to PHP by the way.
Thing is:
I want to dynamically fill a second dropdown list with entries based on a first dropdown list (I want to show cities based on a selected province).
I managed to get the selected province to an external PHP file with an AJAX call in Javascript.
But when I include the external PHP file in my original PHP file, the variable of the external file is undefined.
The AJAX call is fired with an onchange event on the first dropdown menu.
And maybe you can also help with how I use that variable to get the right content in the second dropdown. I've used a multidimensional Array for that.
HTML:
echo('<select name="provincie" id="provincie" onchange="ProvinciePHP()">');
foreach ($provincie as $provincies){
echo ("<option> $provincies </option>");
}
echo ('</select>');
echo('<select name="stad" id="stad"> </select>')
PHP ARRAY:
$provincie = array(
'Selecteer een provincie',
'Drenthe',
'Flevoland',
'Friesland',
'Gelderland',
'Groningen',
'Limburg',
'Noord-Brabant',
'Noord-Holland',
'Overijssel',
'Utrecht',
'Zeeland',
'Zuid-Holland',
);
$stad = array(
'Drenthe' => array("Assen", "Emmen", "Hoogeveen", "Meppel"),
'Flevoland' => array("Almere", "Biddinghuizen", "Dronten", "Lelystad"),
'Friesland' => array("Heerenveen", "Joure", "Leeuwarden", "Sneek"),
'Gelderland' => array("Apeldoorn", "Arnhem", "Nijmegen", "Zutphen"),
'Groningen' => array("Delfzijl", "Groningen", "Stadskanaal", "Veendam"),
'Limburg' => array("Maastricht", "Roermond", "Sittard", "Venlo"),
'Noord-Brabant' => array("Breda", "Den Bosch", "Eindhoven", "Tilburg"),
'Noord-Holland' => array("Alkmaar", "Amsterdam", "Haarlem", "Hilversum"),
'Overijssel' => array("Deventer", "Enschede", "Hengelo", "Zwolle"),
'Utrecht' => array("Amersfoort", "Breukelen", "Utrecht", "Zeist" ),
'Zeeland' => array("Goes", "Middelburg", "Terneuzen", "Vlissingen"),
'Zuid-Holland' => array("Alphen a/d Rijn", "Den-Haag", "Rotterdam", "Schiedam"),
);
function getProvincie(){
var provincie = $('#provincie option:selected').val();
$.ajax({
type: "POST",
url: "getprovincie.php",
data: {data: provincie},
success: function(data) {
alert(data);
$('#stad').css('display','inline');
},
error: function(data) {
}
});
}
//PHP page to where the AJAX call points:
<?php
$resultaat = $_POST['data'];
echo($resultaat);
So, recently I have been dabbling a bit in cakephp but I have run into an issue I just can't seem to solve. I suspect it's something simple I'm missing (as most cases).
The premise of what I'm trying to do is somewhat self-explanatory in the title: I have a view (my add.ctp) within this add I have a form created with the form helper.
I have multiple selects, the first select is a list of companies. Once the company has been selected, I now want to update the next select based on the selected value using jquery and ajax sending a get request to the controller.
The AJAX request completes successfully however, I cannot seem to access the desirable returned data (a list of projects that belong to the selected company).
To be clear I'm trying to return an array in the success callback
I have read a lot and searched around, but I feel that maybe examples are lacking for v3 cakephp.
Some of my code :
Controller
$projectphase = $this->Projectphases->newEntity();
$data = ['content' => 'hi', 'error' => 'nothing found'];
$projects = array('0' => 'Select something');
if($this->request->is('ajax')){
$company_id = $this->request->data('company_id');
$projects = $this->Projectphases->Projects->find('list', ['limit' => 2, 'conditions' => ['company_id' => $company_id]]);
$arr = array();
$arr = $this->chainedProjects($company_id);
$data = ['content' => 'hello', 'error' => ''];
$this->set(compact('projects', 'data'));
$this->set('_serialize', ['projects', 'data']);
}elseif($this->request->is('post')){
debug("hit post");
die();
}
Public function chainedProjects
$projects = $this->Projectphases->Projects->find('list', ['limit' => 2, 'conditions' => ['company_id' => $id]]);
$projs = $projects->toArray();
$values = array();
$x = 0;
foreach ($projs as $key => $value) {
$values[$x] = "<option value='$key'>$value</option>";
$x++;
}
return $values;
Javascript [jquery ajax]
$(document).ready(function(){
$('#company').change(function () {
$company_id = $('#company').val();
var data = {
'type' : 'dropdown',
'company_id' : $company_id
};
$.ajax({
type : 'GET',
//url : 'delegate1/projectphases/add',
data : data,
encode : true,
beforeSend: function(xhr){
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
},
success: function(response){
console.log('success');
console.log(response.content);
console.log(response.message);
//console.log(data.response);
//console.log(result.content);
console.log(response);
}
}).done(function(){
console.log('done');
})
});
})
Jquery 2.1.3
Any help whatsoever will be appreciated!
I have two tables, has-many relationship,
in the master add.ctp, allow user to upload 0~5 files(file path information are stored in details table)
I want to dynamically display attachment(detail) form in the master/add.ctp
1, user choose number of files want to upload from dropdown list,
echo $this->Form->input('attachments', array( 'options' => array(1, 2, 3, 4, 5),'empty' => '(choose one)', 'onchange' => 'showNumber(this.value)'));
then forloop
{
echo $this->Form->input('attachment_path', array('type'=>'file','label' =>'Attachment, Maximum size: 10M'));
}
//but I don't know how to capture this.value, I know Javascript can not pass value to php.
or user click 'add another attachment' link, then detail form shows up.
How to achieve this function, any help would be appreciated.
I have read this article:
Assign Javascript variable to PHP with AJAX
and get same error: the variable is undefined
Edit:
http://cakephp.1045679.n5.nabble.com/Adding-fields-to-a-form-dynamically-a-complex-case-td3386365.html
'For each field use a default name with [] at the end (which will make
it stack like a array) example: data[][book_id] after the fields have
been submitted'
Where should I place the []?
I think you should use Ajax for this.
Simply create an ajax call on select.change() and then a method in the controller that returns the necessary info.
You can return an array of data using echo json_encode(array('key' => 'value')) directly on your controller (or better in a custom view) and access it with Javascript:
success: function(data) {
alert(data.key);
}
Edit...
In your javascript use something like...
$('select').change(function(e) {
var select = $(this);
$.ajax({
type: "POST",
dataType: "json",
url: "/attachments/youraction",
data: { data: { id: select.find(":selected").val() } },
success: function(data) {
for (i in data) {
var input = $('<input>', {type: "file", label: data[i].Attachment.label})
$('form.your-form').append(input);
}
}
})
});
Then in "Yourcontroller" create "youraction" method:
<?php
class AttachmentsController extends AppController
{
public function youraction()
{
if (!$this->RequestHandler->isAjax() || !$this->RequestHandler->isPost() || empty($this->data['id']))
{
$this->cakeError('404');
}
// Do your logic with $this->data['id'] as the select value...
$data = $this->Attachment->find('all', array('conditions' => array('id' => $this->data['id'])));
// ....
// then output it...
echo json_encode($data);
// This should be done creating a view, for example one named "json" where you can have there the above echo json_encode($data);
// Then..
// $this->set(compact('data'));
// $this->render('json');
}
}
It's more clear now?? If you have doubts about ajax + cakephp you should do a search on the web, where you will find a lot of tutorials.
I use this approach to achieve this function. (finally got it :))
http://ask.cakephp.org/questions/view/foreach_loop_with_save_only_saving_last_member_of_array
Yes, AJAX can do lots of things, to me, it's very hard to understand the logic in a day..
Anyway, Thanks again.