How to use route for dependent relationship in octobercms? - php

I am currently working on a front-end form using ajax data request. In my code i have this in the php block that gets displayed in a partial when a category in select-box is selected to show subcategories.
function onChangeCat()
{
$this['subs'] = Cat::whereHas('parent', function ($query) use($cats){
$query->where('cats','=', $cats );
})->pluck('cat_title', 'id');
I am trying to connect it to a route so that when a user clicks on a category, related subcategories get displayed in the second select-box.
This is my route file with #id of category select-box as parameter
Route::get('ajax/{cats}' , function () {
//
return json_encode();
});
How do i connect the codes in php block and routes to work so that only related subcategories of category is displayed?

To pass current element value to Ajax Handler you need to give it name - attribute and add data-request="onChange" handler. all other stuff will be handled by October CMS Ajax Api
<select name="country" data-request="onChange">
<option id="1">A</option>
<option id="2">B</option>
<option id="3">C</option>
<option id="4">D</option>
</select>
In your Ajax handler
function onChange() {
$id = post('country'); // as we name it `country` for select
// ^ - this will be your selected value [id]
return ['data' => 'some data'];
}
Further process data [ IF its needed ] Other wise you can just use data-request-update="calcresult: '#result'" with returning Html Markup
<script>
function myFunction(data) {
console.log(data)
}
</script>
<select
name="first"
data-request="onChange"
data-request-success="myFunction(data)">
...
</select>
Up on success-full request this will call myFunction with return data in our case it will be {'data':'some data'} JSON Object, whatever you return from the Ajax-Handler.
if any doubt please comment.

October CMS has a $this->params() method which can be called to get url parameters from the current request (see here). Your code should look like the following (untested):
Route::get('ajax/{cats}' , function () {
$results = Cat::whereHas('parent', function ($query) {
$query->where('cats', $this->param('cats'));
})->pluck('cat_title', 'id')->all();
return $results;
}

Related

Select a value in drop-down automatically based on controller in codeigniter?

I Want to Select a value in drop-down automatically based on controller in
codeigniter,when a view is loaded then select field value is auto select by the
controller as per requirment. basically i want to manage the drop down from
controller.
What should i need to do?
For Example:-
My View File Code is
<select id="category">
<option value="first">first</option>
<option value="second">second</option>
<option value="Third">Third</option>
<option value="fourth">fourth</option>
</select>
Here is my controllers
firstcontroller,secondcontroller,thirdcontroller,fourthcontroller
Required Code:- firstcontroller load select field value is first.
same as secondcontroller - second then third, fourth are in same way.Is there a way to manage the slect field from controller.
Could you not just pass an argument to your view telling it which controller is being handled?
Alternatively if you got an instance of the CI object you could parse the URL to see which controller was requested.
$CI =& get_instance();
$controller = $CI->uri->segment(1);
$controller_pretty = str_replace('controller', '', $controller);
Best way to make it, is to deal with URI Class by using $this->uri->segment(n).
In your controller, lets say in controllers/firstcontroller.php write the next code:
class Firstcontroller extends CI_Controller{
public function index()
{
// Load form helper
$this->load->helper('form');
// First we need to catch first segment of the URL as it's name of the controller
// so $this->uri->segment(1) will be the first part/segment after your base url (www.website.com/segment1)
$current_controller = $this->uri->segment(1);
// Array of available options for dropdown element
$dropdownOptions = array(
'firstcontroller' => '1st Controller',
'secondcontroller' => '2nd Controller',
'thirdcontroller' => '3rd Controller',
'fourthcontroller' => '4th Controller',
);
// Assign a form_dropdown function to variable for later use in our view file
// form_dropdown will generate a <select /> html element for you
$data['dropdown'] = form_dropdown('dropdown_name', $dropdownOptions, $current_controller);
// Load a view with datas
$this->load->view('samplepage', $data);
}
}
And in your views/dropdownpage.php file put this:
Dropdown:
<?php echo $dropdown;?>

Sending ajax request for each element?

I have an app that has rows, each row contains data. The rows are created by the user (just cloning a sample row).
My ajax function looks like this.
save : function(el) {
//Renaming the properties to match the row index and organize
jQuery('#application-builder-layout .builder-row').each(function(row) {
// Iterate over the properties
jQuery(this).find('input, select, textarea').each(function() {
// Save original name attr to element's data
jQuery(this).data('name', jQuery(this).attr('name') );
// Rewrite the name attr
jQuery(this).attr('name', 'application[rows]['+row+'][elements]['+jQuery(this).attr('name')+']');
});
});
//Looping through each row and saving them seperately with new rowkey
setTimeout(function() {
// Iterate over the layers
jQuery('#application-builder-layout .row-box').each(function(row) {
// Reindex layerkey
jQuery(this).find('input[name="rowkey"]').val(row);
// Data to send
$data = jQuery('#application-builder-layout .row-box').eq(row).find('input, textarea, select');
//$data = $data.add( jQuery('#application-builder-layout') );
jQuery.ajax(jQuery('#form').attr('action'), {
type : 'POST',
data : $data.serialize(),
async : false,
success: function( response ) {
//console.log( response );
}
});
});
}, 500);
},
This is the jQuery, it's application style format so this function is inside a var and is called inside a submit function, the problem is not the ajax, looking at it in the console it saves the data fine, just like I have before.
The Problem I cant get all the data into the database (only the last ajax request) take a look below at "Form Data" it shows what my ajax data looks like and how it's inserting into the DB vs how it should insert, I am using json encode and usually this works, but recently I switched to OOP style coding in PHP so I am not sure if that changes anything?
The PHP:
class MyApp {
const Post_Type = 'page';
public function __construct() {
// register actions
add_action('init', array(&$this, 'init'));
}
public function init() {
// Initialize Post Type
add_action('save_post', array(&$this, 'save_post'));
}
//The main save method
public function save_post($post_id) {
// Empty the builder
if($_POST['rowkey'] == 0) {
$builder = array();
}
$builder['rows'][$_POST['rowkey']] = $_POST['application']['rows'][$_POST['rowkey']];
$builder = esc_sql(json_encode($builder));
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if($_POST['post_type'] == self::Post_Type && current_user_can('edit_post', $post_id)) {
// Update the post's meta field
update_post_meta($post_id, 'MY_DATABASE', $builder);
} else {
return;
}
}
}
The above works fine, except its not inserting the data as an array just inserting the last ajax post call, not each. I am sure in my save method I need to reconfig that somehow, but I am just hacking away and cant find info on the web, so I could really use some insight.
I hope I provided enough.
My code summed up: Just to be clear on whats going on here, let me you some basic HTML of my app.
//This gets cloned and the jQuery renames the rowkey to match the index.
<div class="row-box">
<input type="hidden" name="rowkey" value="0">
<div class="builder-row">
<textarea style="display: block;" name="html"></textarea>
<textarea style="display: block;" name="breakingbad"></textarea>
</div>
</div>
So summed up lets say there is 4 rows, the jQuery renames each row, then loops through each and submits an ajax call for each of them. Then the PHP handles the $_POST, in prior applications working with my custom DB I got it to work but working with wp database I am having issues, maybe I am missing something in my method?
Form Data: the ajax form data looks like this (this is the form data inside headers which can be found in the console(firbug) or network(chrome))
//First element
rowkey:0
application[rows][0][elements][html]:A
application[rows][0][elements][breakingbad]:123
Then if there is another row ajax posts again
//Second element
rowkey:1
application[rows][1][elements][html]:B
application[rows][1][elements][breakingbad]:456
So an and so forth, the database looks like this
{"rows":{"2":{"elements":{"html":"B","breakingbad":"456"}}}}
It should be more like this
{"rows":[{"elements":{"html":"A","breakingbad":"123"},{"elements":{"html":"B","breakingbad":"456"}]}
Holy Smokes Batman: I think I got it, It all resides inside how I handle the $_POST ill update soon with an answer..
The database looks good like this
{"rows":[
{"elements":{"html":"A","breakingbad":"123"}},
{"elements":{"html":"B","breakingbad":"456"}}]
}
Now I can continue to build.. whew this was a MASSIVE headache.

Using one delete function for a post jquery request of php request

I'm looking to find out how I can accomplish this next task. I have a controller that loads a view with a table that lists pages in my database. In every row that is made in the table there is a spot for a icon that when clicked will do one of two things.
If the user does not have javascript enabled:
Clicking on the icon will redirect to the delete function in the controller with id of the page as a paramter
Delete controller function will run delete function in model sending page id to delete model function
Delete function in model will delete the page from the database and when returned back to page controller delete function it will redirect back to index function to show list of pages table again.
After redirect it will display a title and message as to a success/fail.
If the user does have javascript enabled:
Send a post to the delete function in controller with jquery post
method with the data page id
Delete controller function will run delete function in model sending page id to delete model function
Delete function in model will delete the page from the database and when returned back to page controller delete function it create a message array for the json object to return to the success function of the post request.
A message with my pnotify plugin will create a message that is formed from that json object and display it to the user
What I would like to know is with doing this how to properly accommodate for these two scenarios? I have started attempting this but would like to some clarification if I have made a mistake so far.
<?php
// Controller delete function
public function delete($content_page_id)
{
if (isset($content_page_id) && is_numeric($content_page_id))
{
$content_page_data = $this->content_page->get($content_page_id);
if (!empty($content_page_data))
{
//update is ran instead of delete to accompodate
//for the soft delete functionality
$this->content_page->update('status_id', 3);
if ($this->input->is_ajax_request())
{
//return json data array
}
}
}
}
?>
Global JS file to be used for multiple tables with delete buttons
/* Delete Item */
$('.delete').click(function(event) {
event.preventDefault();
var item_id = $(this).attr('rel');
$.post(<?php echo current_url(); ?>'delete', { item_id : item_id }, function(data)
{
if (data.success)
{
var anSelected = fnGetSelected( oTable );
oTable.fnDeleteRow( anSelected[0] );
}
}, 'json');
});
I think that you should have two functions in PHP:
public function delete($content_page_id) {
// Your delete code
return "a string without format";
}
public function deleteAjax($content_page_id) {
return json_encode($this->delete($content_page_id));
}
So, when the user has JS enabled, you call deleteAjax passing a parameter in your $.post function to let PHP know that JS is enabled:
$.post(<?php echo current_url(); ?>'delete', { item_id : item_id, js: 1 }, function(data)
{
if (data.success)
{
var anSelected = fnGetSelected( oTable );
oTable.fnDeleteRow( anSelected[0] );
}
}, 'json');
And if JS is disabled, call the other function. You should use an AJAX specialized controller instead a function in the same class.
1) As far as "displaying a message" - the view-itself could be ready for a 'message' if one exists. Bringing us back to...
2) Can you have your delete function return the message you want displayed? Your AJAX approach will ignore this message while your View will display it...
3) I agree that your 'Controller delete function' should 'finish' with different outcomes based on whether the request is AJAX or not. I like what #Skaparate (answered Aug 30 at 18:37) was doing with adding: js:1 In your delete function, you could use this in a simple conditional:
if js = 1
header('HTTP/1.1 200');
else
call view and include/pass-in the 'message'

How to call a function of component from view?

Q1 : How to call a function of component from view?
one of my function is using most of the controllers.
public function actionDynamicdepartment()
{
//Department
$data = Department::model()->findAll('p_id=0 AND company_id=:company_id', array(':company_id'=>(int) $_POST['company_id']));
$data = CHtml::listData($data,'id','name');
$dddepatment = "<option value=''>Please select a department</option>";
foreach($data as $value=>$name)
$dddepatment .= CHtml::tag('option', array('value'=>$value),CHtml::encode($name),true);
//Section and Team
$ddsection = "<option value=''>Please select a section</option>";
$ddteam = "<option value=''>Please select a team</option>";
// return data (JSON formatted)
echo CJSON::encode(array(
'dddepartment'=>$dddepatment,
'ddsection'=>$ddsection,
'ddteam'=>$ddteam
));
}
I want to put it into component or some place.
And I want to call those function from my views. e.g
<div class="row">
<?php echo $form->labelEx($model,'company_id'); ?>
<?php
$records = Company::model()->findAll();
$company = CHtml::listData($records, 'id', 'name');
echo $form->dropDownList($model,'company_id', $company, array('prompt'=>'Please select a company',
'ajax' => array(
'type'=>'POST', //request type
'url'=>CController::createUrl('department/dynamicdepartment'), //url to call.
'dataType'=>'json',
'data'=>array('company_id'=>'js:this.value'),
'success'=>'function(data) {
$("#FaMovehistory_department_id").html(data.dddepartment);
$("#FaMovehistory_section_id").html(data.ddsection);
$("#FaMovehistory_team_id").html(data.ddteam);
}',
)
)
);
?>
</div>
Or
Q2 : put those function at one of the controller (department.php). And can I call those function from different view?
Q3 : if do as Q2, is there any traffic?
What I use to do is to define a CWidget (like Dmitry said) and then I create some functions (I tend to make them static, as if it was a library), so if, for instance, your Widget is called "Departments", you could do something like this:
Yii::import("application.components.Departments");
Departments::actionDynamicdepartment();
Pretty straightforward. You could, for this situation, return that CJson instead of echoing. However, you may not be interested in having a static response from this method.
For your last questions, I tend to approach the population of dropdowns in a more classic manner, having an ajax call (I use jquery) requesting a central controller and passing some variables to it. That, of course, generates traffic.
So, to sum up, if you want to recieve a list of departments and avoid changing it during the current page, you could go for a widget/component. If, on the other side, your dropdown needs to be responsive along with the rest of the items in a form, a controller's action is your best (and probably unique) option.
You need to create a widget instead of component.
Each widget has its own view, and you will be able to describe in its class logic of his behaviour (move the code from the controller) Then call it in the main view:
<?php $this->widget('path.to.your.widget') ?>
Read more: http://www.yiiframework.com/doc/api/1.1/CWidget and http://www.yiiframework.com/doc/guide/1.1/en/basics.view#widget

Use ajax to fill cities in a dropdown in a mvc based php application?

In a PHP MVC application, the model part has a city.php file that defines a city class.
The city class has a method to fetch all cities for a province i.e.
getCitiesByProvince('ProvinceId')
When the user selects a province from a province dropdown, I need to make an ajax call to getCitiesByProvince('ProvinceId') depending upon what value for Province Id was selected by the user inside the Province dropdown.
How do I do this?
Edit: 1) The page uses the GET method and not the POST method. 2) The controller file uses a switch($action) to execute a specific case. For example to fetch all cities
case 'cities': //Get all cities for a provinceId
$city= new city();
$cities = $City->getCitiesByProvince('ProvinceId');
echo json_encode($cities);
Action is probably a hidden html attribute that tells the php script what action/case to perform... maybe something like
<input type="hidden" name="action" value="cities" />
This is another developer's code that i'm not too familiar with at the moment and i'm just trying to guess how things work by looking into various files...
Have your PHP file do the following:
<?php
$province = $_GET['p'];
$cities = array();
$city_results = ... // fetch cities from database
foreach($city_results as $city_result) {
$cities[] = $city_result->city;
}
echo json_encode($cities);
?>
Have your Javascript do the following:
$.ajax({
type: "GET",
url: "php_url_path",
data: { p: get_province_here() },
success: function (cities) {
for (var i = 0; i < cities.length; i++) {
... // handle options here
}
}
});
This will create the inter-file connection that you seek. Enjoy and good luck!
You wouldn't be able to call this straight from the model insted you'd need to make an action in the controller called getcities or whatever and use $.ajax or $.get or $.post or $.getJSON to retreve the results assuming they'd be in json format heres an example using $.post
if your controller is citycntrl.php inside the controller you would do
//whatever logic to get an array of cities in whatever format you'd like
ex: '{zip}' => '{cityname}', or just {cityname} with regular keys
using the $_POST['providenceId']; key were sending with jQuery
What you'd want to do is run the array through json_encode($arrayname); and echo that out in your controller based on the providenceId post value.
Heres a better code example for your drop down senario i misread the first time and missed the drop down part
$.post('controller/getcities', {
provinceId: $('#{dropdownIDorCLASS}:selected').val();
}, function (data) {
//data will contain your list of cities passed down from your controller.
//do whatever with returned json data
}, 'json');
if I'm just confusing the crap out of you feel free to contact me on Skype and i hopefully assist a bit better UN: fallen.networks

Categories