⚠ In case you've missed it, we have migrated to our new website, with a brand new forum. For more details about the migration you can read our blog post for website migration. This is an archived forum. ⚠

  •     

profile picture

categories and subcategories



capizhe

capizhe
  • profile picture
  • Member

Posted 04 January 2012 - 17:27 PM

hi guys.

I have Categories and sub-categories in my database.
and when i insert a new product I need the select subcategories box change depending of the categories
selection.

How can I do that?

[img]http://img860.imageshack.us/img860/4253/asdsr.jpg[/img]



PD: sorry for my english.

Moslem Mansouri

Moslem Mansouri
  • profile picture
  • Member

Posted 24 February 2012 - 17:00 PM

I have this problem
How should we fix it?

KaBaDaBrA

KaBaDaBrA
  • profile picture
  • Member

Posted 01 March 2012 - 14:17 PM

Hey guys - I was busy building my own quick frontend solution to it using jQuery

Here is my code:


<script type="text/javascript">
$(document).ready(function(){
//PARENT DROPDOWN
var parent = $('select[name="clientID"]');
//CHILD DROPDOWN
var child = $('select[name="propertyID"]');

parent.change(function() {

var select_value = this.value;
parent.show();
child.show();

//HIDE THE FANCY JQUERY PARENT DROPDOWN
var divs = parent.next().find('div').hide();
divs = parent.next().find('a').hide();
divs = parent.next().find('span').hide();

//REMOVE ALL CURRENT OPTIONS FROM CHILD DROPDOWN
child.find('option').remove();

//POST TO A CUSTOM CONTROLLER ADDING OPTIONS | JSON
var myOptions = {
val1 : 'First Option',
val2 : 'Second Option'
};

$.each(myOptions, function(val, text) {
child.append(
$('<option></option>').val(val).html(text)
);
});

//HIDE THE FANCY JQUERY CHILD DROPDOWN
var divs = child.next().find('div').hide();
divs = child.next().find('a').hide();
divs = child.next().find('span').hide();
});
});
</script>


Basically it hides the fancy drop down box and displays the good old HTML version. I wanted to use the fancy one but not sure how to recall the jQuery script to "rebuild" the fancy box with the new options when the onchange event is made. Maybe someone can enhance the code and re-work from there but the above code works perfectly for me.

Just use the form field name e.g. select[name="your_parent_selector"] and select[name="your_child_selector"]

Cool - hope it helps!!

KaBaDaBrA

KaBaDaBrA
  • profile picture
  • Member

Posted 02 March 2012 - 09:53 AM

Here is a better example after getting some kick-ass info from web-johnny...

jQuery/Javascript:


$(document).ready(function(){

//PARENT DROPDOWN
var parent = $('select[name="clientID"]');
//CHILD DROPDOWN
var child = $('select[name="propertyID"]');

parent.change(function() {

var select_value = this.value;

//REMOVE ALL CURRENT OPTIONS FROM CHILD DROPDOWN
child.find('option').remove();

//POST TO A CUSTOM CONTROLLER ADDING OPTIONS | JSON
var myOptions = "";

//YOUR CONTROLLER URL AND PARENT KEY
$.getJSON('<?php echo site_url(); ?>reports/get_properties/'+select_value, function(data) {

$.each(data, function(key, val) {
child.append(
$('<option></option>').val(val.value).html(val.property)
);
});

parent.each(function(){
$(this).trigger("liszt:updated");
});

child.each(function(){
$(this).trigger("liszt:updated");
});

});
});
});


My PHP Controller


//GET JSON OF PROPERTIES
function get_properties()
{
$clientID = $this->uri->segment(3);

$this->db->select("*")
->from('clients_properties')
->where('clientID', $clientID);
$db = $this->db->get();

$array = array();
foreach($db->result() as $row):
$array[] = array("value" => $row->property_id, "property" => $row->property_title);
endforeach;

echo json_encode($array);
exit;
}

vnt

vnt
  • profile picture
  • Member

Posted 07 March 2012 - 20:38 PM

Hi KaBaDaBrA,
I need your help!
In which file should I put the code jQuery/Javascript.
Can you give me an example of how to call the function: function get_properties()

thank you very much!

KaBaDaBrA

KaBaDaBrA
  • profile picture
  • Member

Posted 11 March 2012 - 09:27 AM

Hey vnt,

You put the code directly in the view where it calls the css, jscript etc.

Example of the page:


<?php
foreach($css_files as $file): ?>
<link type="text/css" rel="stylesheet" href="<?php echo $file; ?>" />
<?php endforeach; ?>
<?php foreach($js_files as $file): ?>
<script src="<?php echo $file; ?>"></script>
<?php endforeach; ?>


<div>
<?php echo $output; ?>
</div>

<script type="text/javascript">
//all script goes in here - personally I like adding my script to the bottom of the page
</script>

Cèsar Martí

Cèsar Martí
  • profile picture
  • Member

Posted 16 March 2012 - 16:02 PM

Hi KaBaDaBrA.

I think it's really necessary this kind of "categories and subcategories" dropdown selects. I was trying your solution, but it didn't work. Could you make a real example of this and upload somewhere or explain, step by step, how to make it work.

Thanks a lot.

KaBaDaBrA

KaBaDaBrA
  • profile picture
  • Member

Posted 17 March 2012 - 10:23 AM

Hi there

I made a quick example / tutorial on how to create categories and subcategories by using jQuery. I based my example on Country -> State -> City

View / Download it here - click on "Add Customer" to see it in action.

Hope this all makes sense :D Feel free to ask me anything if you get stuck - if you're familiar with jQuery it's very easy.

web-johnny

web-johnny
  • profile picture
  • Administrator
  • 1,166 posts

Posted 17 March 2012 - 11:34 AM

Impresive :) . I will add it to extra coding so other people can use it.

KaBaDaBrA

KaBaDaBrA
  • profile picture
  • Member

Posted 17 March 2012 - 11:39 AM

[quote name='web-johnny' timestamp='1331984048' post='818']
Impresive :) . I will add it to extra coding so other people can use it.
[/quote]

Awesome thanks man! I think this will help a lot of the guys struggling with dependent select boxes :)

web-johnny

web-johnny
  • profile picture
  • Administrator
  • 1,166 posts

Posted 17 March 2012 - 11:42 AM

Yes I also think the same thing. There where lot of requests. Some of them also say that there is even more important that the multilingual functionality, to have this feature! I just didn't have time to do this. And the great thing is that it is at the new version 1.2 :D

Thanks

KaBaDaBrA

KaBaDaBrA
  • profile picture
  • Member

Posted 17 March 2012 - 20:30 PM

I tweaked the code a little and created a more dynamic and easier way to implement this instead of having to change the jQuery.

Add this to the top of the view:



//LOAD CRUD
$crud = new grocery_CRUD();
//SETUP DEPENDENT DROPDOWN
$dependent_dropdown = array(
//GET THE STATE OF THE CURRENT PAGE - E.G LIST | ADD
'state' => $crud->getState(),
//SETUP YOUR DROPDOWNS
//Parent field item always listed first in array, in this case countryID
//Child field items need to follow in order, e.g stateID then cityID
'dropdowns' => array('countryID','stateID','cityID'),
//SETUP URL POST FOR EACH CHILD
//List in order as per above
'url' => array('', site_url().'/examples/get_states/', site_url().'/examples/get_cities/')
);


Replace the Javascript at the bottom with the following:


if($dependent_dropdown['state'] == 'add' || $dependent_dropdown['state'] == 'edit')
//DONT HAVE TO EDIT THE CODE BELOW IF YOU DONT WANNA :P
echo '$(document).ready(function() {';
for($i = 0; $i <= sizeof($dependent_dropdown['dropdowns'])-1; $i++):
//SET VARIABLES
echo 'var '.$dependent_dropdown['dropdowns'][$i].' = $(\'select[name="'.$dependent_dropdown['dropdowns'][$i].'"]\');';
//HIDE ALL CHILD ITEMS
if($i > 0 && $dependent_dropdown['state'] == 'add') {
echo '$(\'#'.$dependent_dropdown['dropdowns'][$i].'_input_box\').hide();';
}
endfor;
for($i = 1; $i <= sizeof($dependent_dropdown['dropdowns'])-1; $i++):
//CHILD DROPDOWNS
echo $dependent_dropdown['dropdowns'][$i-1].'.change(function() {';
echo 'var select_value = this.value;';
//REMOVE ALL CURRENT OPTIONS FROM CHILD DROPDOWNS
echo $dependent_dropdown['dropdowns'][$i].'.find(\'option\').remove();';
//POST TO A CUSTOM CONTROLLER ADDING OPTIONS | JSON
echo 'var myOptions = "";';
//GET JSON REQUEST OF STATES
echo '$.getJSON(\''.$dependent_dropdown['url'][$i].'\'+select_value, function(data) {';
//APPEND RECEIVED DATA TO STATES DROP DOWN LIST
echo $dependent_dropdown['dropdowns'][$i].'.append(\'\');';
echo '$.each(data, function(key, val) {';
echo $dependent_dropdown['dropdowns'][$i].'.append(';
echo '$(\'\').val(val.value).html(val.property)';
echo ');';
echo '});';
//SHOW CHILD SELECTION FIELD
echo '$(\'#'.$dependent_dropdown['dropdowns'][$i].'_input_box\').show();';
//MAKE SURE CITY STILL HIDDEN INCASE OF COUNTRY CHANGE
for($x = $i+1; $x <= sizeof($dependent_dropdown['dropdowns'])-1; $x++):
echo '$(\'#'.$dependent_dropdown['dropdowns'][$x].'_input_box\').hide();';
endfor;
//RESET JQUERY STYLE OF DROPDOWN LIST WITH NEW DATA
echo $dependent_dropdown['dropdowns'][$i-1].'.each(function(){';
echo '$(this).trigger("liszt:updated");';
echo '});';
echo $dependent_dropdown['dropdowns'][$i].'.each(function(){';
echo '$(this).trigger("liszt:updated");';
echo '});';
echo '});';
echo '});';
endfor;
echo '});';


The code that you pasted at the top you can change to your needs.

For example say you want to load up a cars list by make and model you would use something like this:


//LOAD CRUD
$crud = new grocery_CRUD();
//SETUP DEPENDENT DROPDOWN
$dependent_dropdown = array(
//GET THE STATE OF THE CURRENT PAGE - E.G LIST | ADD
'state' => $crud->getState(),
//SETUP YOUR DROPDOWNS
'dropdowns' => array('make_id','model_id'),
//SETUP URL POST FOR EACH CHILD
//List in order as per above
'url' => array('', site_url().'/examples/get_models/')
);


I added the dynamic example into the download - example (dynamic).php

KaBaDaBrA

KaBaDaBrA
  • profile picture
  • Member

Posted 18 March 2012 - 13:23 PM

I added in a loader image that displays next to the drop down as the child drop down loads.

Example here: http://demo.edynamics.co.za/grocery_crud/index.php/examples/customers_management/add

I also added it to the dynamic view example located in the downloaded file :)

fleep

fleep
  • profile picture
  • Member

Posted 25 March 2012 - 08:42 AM

Hi KaBaDaBra !

Your script is amazing, it's exactly what I was looking for.
It works fine, but something sucks :

in your form example, if I choose
Country : United States
State : California
City: test 5

If i look into the code source, I see that it has been also populated the following : test 1, test 2, test 3 and test 4
Those ones that we don't actually need to load if we chose California state.

Ok, it seems nothing in this example, but I am using a database of 36000 cities, and when I choose my state, it takes over a minute to load all those 36000 cities, instead of loading only the 200 cities corresponding to this state.

You can try here : http://www.veloccasi..._management/add
(it may take some time to load too)

Is there a way to load dinamically the cities, corresponding to the chosen state ?

And also : what's the difference between :
[i][b]example (dynamic).php[/b][/i]
and
[i][b]example.php[/b][/i]
I tried both of them but nothing changed

Thanks !

KaBaDaBrA

KaBaDaBrA
  • profile picture
  • Member

Posted 25 March 2012 - 09:20 AM

Hi fleep - can you attach your sql for me and I will quickly try write a solution for you if I can :D

Also just double check your function where you are calling the cities that they are being called per stateID so that it shouldnt have to load all 36000 - only the ones as per the stateID.

fleep

fleep
  • profile picture
  • Member

Posted 25 March 2012 - 09:58 AM

Thanks for the quick reply !

Here is the SQL (I deleted 90% of the cities cause the file was too big),

actually, I didn't changed your code, I just changed the table names and column names to match yours.
So everything is exactly the same, except the datas in the tables.

And in your example, when I select the third option (city), we still can see in the source code that all the cities appear, even the one that doesn't correspond to the chosen state.
I'm not good enough in PHP to see what's wrong :/

fleep

fleep
  • profile picture
  • Member

Posted 25 March 2012 - 10:02 AM

Here is the call of the cities

//GET JSON OF CITIES
function get_cities()
{
$stateID = $this->uri->segment(3);

$this->db->select("*")
->from('city')
->where('stateID', $stateID);
$db = $this->db->get();

$array = array();
foreach($db->result() as $row):
$array[] = array("value" => $row->city_id, "property" => $row->city_title);
endforeach;

echo json_encode($array);
exit;
}

KaBaDaBrA

KaBaDaBrA
  • profile picture
  • Member

Posted 25 March 2012 - 10:40 AM

I see what's happening - On the creation of the cities via GCRUD it creates ALL the cities in the cityID dropdown. What slows it up the first time is jQuery trying to dynamically remove all 36000 cities from the cityID when you select a province. You will notice after the first select it then goes pretty smoothly. I would probably try use a callback_add_field / callback_edit_field - but not quite sure how to do it yet. Maybe web-johnny has a simpler solution on how not to populate the cityID field as the crud is generating...

EDIT: Can you try add this in the view of your code where


if($i > 0 && $dd_state == 'add') {
//HIDE ALL CHILD ITEMS
echo '$(\'#'.$dd_dropdowns[$i].'_input_box\').hide();';
}


change to


if($i > 0 && $dd_state == 'add') {
//HIDE ALL CHILD ITEMS
echo '$(\'#'.$dd_dropdowns[$i].'_input_box\').hide();';

//REMOVE CHILD OPTIONS
echo '$('.$dd_dropdowns[$i].').children().remove().end();';
}


Might be a quicker way to remove child options using jQuery - but can only test using your huge city list online.... lemme know if it works :)

If you're using my older example just change $dd_dropdowns to $dependent_dropdown['dropdowns']

fleep

fleep
  • profile picture
  • Member

Posted 25 March 2012 - 11:33 AM

I did the changes, but it's worse : page loading is twice longer as before.
And all the 36000 cities still appears in the source code :wacko:

I'll ask a friend of mine this afternoon, he might have the answer :)

KaBaDaBrA

KaBaDaBrA
  • profile picture
  • Member

Posted 25 March 2012 - 11:40 AM

[quote name='fleep' timestamp='1332675233' post='916']
I did the changes, but it's worse : page loading is twice longer as before.
And all the 36000 cities still appears in the source code :wacko:

I'll ask a friend of mine this afternoon, he might have the answer :)
[/quote]

Cool let me know...the only thing I can think of for now is getting GCRUD not to populate the states/cities on load but instead return a blank select :D