I have done very much research on this topic but I cannot find how i can do this. I am trying to add data to the $data parameter in a view that is being called from the controller of another view. However, any data i add to the subview via the subcontroller cannot be accessed by the subview. However, when I try to pass data to the subview via the client view, it works just fine. Most of the fixes on SO seem to reference just calling the $key in $data['key'] rather than $data so that doesn't seem really relevant here...
I have two classes:
welcome.php - a page
welcomemenu.php - a set of controls intended to
be loaded into welcome.php
Here is my Client Controller (the page that it's on, welcome.php), which stores the return val from subview $welcomemenu in its own $data array...:
<?php
class Welcome extends CI_Controller {
function __construct() {
parent::__construct();
}
function index() {
//echo 'this is the Welcome index function';
$data['clienttestdata'] = 'data from welcome.php!';
$data['welcomemenu'] = $this->load->view('welcome/welcomemenu', $data, true);
$this->load->helper('url');
$this->load->view('templates/header');
$this->load->view('pages/welcome', $data);
$this->load->view('templates/footer');
}
}
And here is the client view ("welcome_view.php" - seems simple enough. The $welcomemenu var is where I put the returns from my component class...):
<section id="allWelcomeContent" class="mainBody">
<header id="mainPageHdr" class=mainPageHdr>
<!-- other stuff from my header -->
</header>
<!-- this is where i want to put the welcome menu... -->
<section id="mainWelcomeContent" class="mainContent">
<div>
<?php echo $welcomemenu;?>
</div>
</section>
</section>
And here is the Controller for my sub-component welcomemenu.php:
<?php
class Welcomemenu extends CI_Controller {
public function __construct() {
parent::__construct();
}
public function index() {
$data['menu_items'] = array('About', 'Portfolio', 'Resume', 'Fun', 'Blog');
$data['testdata'] = 'data from welcomemenu.php!';
$this->load->view('welcome/welcomemenu', $data);
}
}
And lastly: Here is the sub-view that is supposed to get data from its own controller, but cannot, even though it can take data from a calling client (i.e., the $clienttestdata shows up fine but $testdata doesn't)!
<section>
<!-- TODO: make this element repeatable so content can load from controller and/or model. -->
<div id="divMenuItems">
<?php echo $clienttestdata;?>
<?php echo $testdata;?>
</div>
</section>
Still i couldn't find any proper solution. if anyone then please give me
When you're including the welcomemenu partial in your Welcome/index method, you have to remember that the view does not go through its own controller. Instead, its contents are returned as a string and stored as a parameter. It gets all of its own parameters through the ones you send to it via $data:
$data['welcomemenu'] = $this->load->view('welcome/welcomemenu', $data, true);
This view will thus have access to everything in $data so far - nothing extra is added through the Welcomemenu controller. So, in the above case, it will have:
array
(
'clienttestdata' => 'data from welcome.php!'
)
If you add the parameters you need to $data (as $data['testdata']), your sub-view will have what it needs.
Related
I'm a bit confused on including a controller / view within another controller/view. I'm doing the following and getting funny rendering issues:
//CONTROLLER About
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Pages extends CI_Controller {
public function about(){ //the standalone about page
$data['about_inner'] = $this->about_inner();
$this->load->view('pages/about',$data);
}
public function about_inner(){ //this is separate so it can be loaded by the landing page without the html shell around it
$this->load->model('about_model');
$data['about'] = $this->about_model->get_content();
$this->load->view('pages/about-inner',$data);
}
}
//view about.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<div class="container about" data-page="about">
<div class="scroll-container about">
<?=$about_inner; ?>
</div>
</div>
</body>
</html>
The issue I'm getting is that $about_inner does not end up loading inside of the "scroll-container" - it loads and renders before everything else, as shown in the screenshot.
What's the best way to get the about_inner view and all of its associated data to load within the about view? I need all the content ($this->about_model->get_content()) to come from about_inner since it can also be loaded by other pages via ajax.
SOLUTION
public function about(){ //the standalone about page
$data['nav'] = $this->load->view('templates/nav', NULL, TRUE);
$data['about_inner'] = $this->about_inner(true);
$this->load->view('pages/about',$data);
}
public function about_inner($print =false){ //this is separate so it can be loaded by the landing page without the html shell around it
$this->load->model('about_model');
$data['about'] = $this->about_model->get_content();
return $this->load->view('pages/about-inner',$data, $print);
}
//HTML
//view about:
<div class="container about" data-page="about">
<?=$nav; ?>
<div class="scroll-container about">
<?=$about_inner; ?>
</div>
</div>
You just need to tell the about_inner function to return the data and not print the data. That's the 3rd argument to function view($template, $data, $return);
$this->load->view('pages/about-inner',$data, true);
If you need to do either or, just set a boolean flag as the argument to the function
function about_inner($print = false){
...
$this->load->view('pages/about-inner', $data, $print);
}
Then when you call the function you can simply pass true to the function in order to get it to return the HTML instead of printing the HTML.
$this->about_inner(true)
if your JS folder is in root you have to define it with base_url() function. So correct all the path in get_content method
Ex
<script src ="<?php echo base_url() ?>path/to/your/folder/aaa.js" .....
And i think you can keep one controller method and remove one.(You can keep about and remove about_inner)
I have a template design for each page and it is working without any issues, now i have a problem with form validation and template.
my_controller //inside my controller
function __construct()
{
parent::__construct();
$this->load->library('template');
}
public function page1(){
$this->template->write('title', 'COMPANY');
$this->template->write_view('content', 'company');
$this->template->render();
}
public function validation(){
//for page1 form validation
//form validation here
if ($this->form_validation->run() == FALSE){
// here i need to call my page1 again to update the form error
// option1: $this->load->view('page1'); // this is just loading page1, not loading with my template, template file has header, footer, js and css file includes
// option2: $this->template->load('template', 'page1'); // it is loading page withing page
// option3: $this->template->write_view('content', 'page1');
// $this->template->render(); // this is same as option2
} else {
$this->load->view('formsuccess');
}
}
So my question is how do i can call same view (within one controller) for multiple time when it is already loaded with template?
EDITED for more clarity
My template file is just single file ( not separated like header, footer) will have all header information and footer information with common style sheet and script files.
I am having
<?php $content ?>
variable name inside the template to pass my content from controller.
for example see my page1 function(),
$this->template->write('title', 'COMPANY'); // to write a value on variable
$this->template->write_view('content', 'page1'); //view page to write on template
$this->template->render(); // final template render
This page is having form validation, if my form validation is FALSE, how do i can reload the template page with validation error?
I have tried so many way, please check my option1, 2, 3, i never got a solution to solve this, now please tell me how do i can solve this?
If I understand correctly, you want to display the validation errors?
Inside your View file, put the following:
Short IF-Statement Form:
<?php if ( validation_errors() ) :?>
<div>
<?php echo $validation_errors();?>
</div>
<?php endif;?>
Regular If-Statement Form:
<?php if ( validation_errors() ) {?>
<div>
<?php echo $validation_errors();?>
</div>
<?php }?>
Validation Errors Doc
I have a register view file on which there is a very big form. Hence I plan to use a form wizard plugin along with the jquery form validation plugin. I only want these scripts loaded on specific pages. How do I do this ? Here is my controller method.
public function index(){
$data['title'] = "Register";
$this->load->view("site_header", $data);
$this->load->view("site_nav");
$this->load->view("content_register");
$this->load->view("site_footer");
}
I saw a similar post on stackoverflow here but I don't understand what to do. Please help.
You can send which js to load as a variable. Example is here;
Sample controller
class mypage extends CI_Controller{
public function index(){
$data['js_to_load']="index.js";
$this->load->view('header',$data);
$this->load->view('my_html_page');
}
public function second_page(){
$data['js_to_load']='second.js';
$this->load->view('header',$data);
$this->load->view('my_second_html_page');
}
}
header.php - View file
<!-- Needed html code here -->
<? if ($js_to_load != '') : ?>
<script type="text/javascript" src="assets/js/<?=$js_to_load;?>">
<? endif;?>
<!-- Other html code here -->
Whats happening?
We are setting the js file into $data variable, and passing the $data variable to header.
In header file we are checking if js_to_load is set? If yes, we are including the js file.
Also you can pass multi js files by using arrays.
Sample controller
class mypage extends CI_Controller{
public function index(){
$data['js_to_load']=array("index.js","index1.js","index2.js");
$this->load->view('header',$data);
$this->load->view('my_html_page');
}
public function second_page(){
$data['js_to_load']=array("second.js","second2.js","second2.js");
$this->load->view('header',$data);
$this->load->view('my_second_html_page');
}
}
header.php - View file
<!-- Needed html code here -->
<? if (is_array($js_to_load)) : ?>
<? foreach ($js_to_load as $row):
<script type="text/javascript" src="assets/js/<?=$row;?>">
<?endforeach;?>
<? endif;?>
<!-- Other html code here -->
Pass an array of js you want added to the header in the data, and add in in the view, there are probably other ways of doing it (this kind smears the controller/view line, so it's a bit dirty, but it works).
public function index(){
$data['title'] = "Register";
$data['js'] = array('link', 'link', etc);
$this->load->view("site_header", $data);
$this->load->view("site_nav");
$this->load->view("content_register");
$this->load->view("site_footer");
}
It is better to load your .js in your footer as your HTML should fully load before your start running script over it.
see here for reasons
i use a universal footer to handle the .js files
public function index()
{
$this->load->view('template/header');
$this->load->view('template/nav');
$this->load->view('thing/landing');
$this->load->view('template/footer');
}
my footer view is
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
$caller_class = $this->router->class;
$caller_method = $this->router->fetch_method();
?>
<script type="text/javascript" src="<?php echo base_url(); ?>public/js/jquery.min.js"></script>
<?php
//look for JS for the class/controller
$class_js = "public/js/custom-".$caller_class.".js";
if(file_exists(getcwd()."/".$class_js)){
?><script type="text/javascript" src="<?php echo base_url().$class_js; ?>"></script>
<?php
}
//look for JS for the class/controller/method
$class_method_js = "public/js/custom-".$caller_class."-".$caller_method.".js";
if(file_exists(getcwd()."/".$class_method_js)){
?><script type="text/javascript" src="<?php echo base_url().$class_method_js; ?>"></script>
<?php
}
?>
</body>
</html>
using $this->router->class; or $this->router->fetch_method(); to detect what controller or method in the controller is being used. then detecting if a .js file exists for that controller/method
with little management you can have controller and/or method specific scripts without fiddling with the footer.
in file pub/js/custom-mycontrollername-mymethod.js you would then use (jquery);
$(document).ready(function() {
if ( $( "#mydivthing" ).length ) {
$('#mydivthing').html("fetching..");
$.ajax({
........
});
} else {
console.log("skipped js segment");
}
});
here the jquery only runs when the document is ready (as jquery recommends)
and you can also use if ( $( "#mydivthing" ).length ) { to check that your div is actually on the page. so you are not firing events when they are not loaded (for speed). but as jquery is likely doing some checking - this is probably only helpful for larger runs of code than just single button clicks events.
while the question was for views, this answers gets to a controller/methods level. so while a method can have multiple views - this still a view/screen as seen by the user.
added bonus that you can associate .js files to controller/methods just by its filename.
you can use a variable as a controller name and pass this variable to your view like this
Here is Controller
class Blog extends CI_Controller{
public function index(){
$data['controller']="blog_index";
$this->load->view('header',$data);
}
public function second_page(){
$data['controller']="blog_second_page";
$this->load->view('header',$data);
}
}
Header.php File
<? if (isset($controller) && in_array($controller,array('blog_index'))) : ?>
<script type="text/javascript" src="assets/js/custom_blog_index.js">
<? endif;?>
<? if (isset($controller) && in_array($controller,array('blog_second_page'))) : ?>
<script type="text/javascript" src="assets/js/custom_blog_second_page.js">
<? endif;?>
<!-- Other html code here -->
hope this will answer your question
I don't understand your problem. I suppose you load your js files in view site_header or view site_footer, why don't you load another view for these pages? for example:
public function index(){
$data['title'] = "Register";
$this->load->view("site_header_extra_js", $data);
$this->load->view("site_nav");
$this->load->view("content_register");
$this->load->view("site_footer_extra_js");
}
Another solution is to put an if in your view to load extra js files checking the path, you can use $this->uri->segment() for this.
I have some experience with php, but I just recently started learning Codeigniter. I used to have a website with a fixed navigation pane and sidebar, but the main section of the site loaded dynamically based on a Get variable. It was basically
include head.php
include navbar.php
include sidebar.php
include the page requested from the get variable (home, about, contact, etc.)
include footer.php
I liked this because the entire site did not have to reload when the user navigated from page to page.
I can't figure out how do this with Codeiginiter. Should I be using a controller for each page or one controller with a function for each page? Do anyone know of a good tutorial that does something similar? All the tutorials I've seen reload the entire site for every page.
Edit: Essentially I want to do this but with Codeigniter
Since it looks like you want relatively static content, but loaded dynamically you can do with one controller and (maybe) one method in the controller.
To do it with one method, do this in the welcome controller:
public page( $page_id ){
// views/header.php
$this->load->view( "header" );
if( $page_id = "about" ){
$this->load->view("about"); // views/about.php
}
else if( $page_id = "contact" ){
$this->load->view("contact"); // views/contact.php
}
// views/footer.php
$this->load->view("footer");
}
This takes a single get variable and figures out what page to load in between the header and footer.
This way www.yoursite.com/page/about will load the about page, www.yoursite.com/page/contact will load the contact page
Now, if you want to get rid of the /page part, you need to do some URL rerouting in application/config/routes.php
Alternatively you could use several methods in one controller:
public about( ){
// views/header.php
$this->load->view( "header" );
$this->load->view( "about" );
// views/footer.php
$this->load->view("footer");
}
public contact( ){
// views/header.php
$this->load->view( "header" );
$this->load->view( "contact" );
// views/footer.php
$this->load->view("footer");
}
Now your URLs look nicer without routing, but you have to load the header/footer for every page.
do you really like to copy/paste many $this->load->view() to any controller function?
It's a spaghetti code. You can try next: for example we have main.php controller as default controller. This main controller contain main function:
public function index()
{
ob_start();
$this->load->model('mainmodel');
$data = $this->mainmodel->_build_blocks(); //return array with needed blocks (header, menu, content, footer) in correct order
foreach ($data->result_array() as $row) {
$this->load->module($row['block_name']);
$this->name = new $row['block_name'];
$this->name->index();
}
ob_end_flush();
}
So, each other controller also have index() function which can dispatch actions depends on url segments, prepare params etc.
Footer controller as example (I use Smarty as template engine):
public function index()
{
$this->mysmarty->assign('year', date("Y"));
$this->mysmarty->view('footer');
return true;
}
Content controller will have:
public function index()
{
$name = $this->uri->segment(1, 'index');
$act = $this->uri->segment(2, 'index');
$this->load->module($name);
$this->name = new $name;
$pageData = $this->name->_show($act);
if ($pageData)
{
$this->mysmarty->assign($name, $pageData);
}
$this->mysmarty->view($name);
}
Thats mean what if you want to show http://site.name/page/contactus , we do next:
1) main.php start cycle by needed blocks
2) firstly we show header.tpl by header controller
3) then we show menu
4) then we call content controller which parse url, found what he should call _show() function in Page controller and pass action='contactus' to it. _show() function can contain some switch/case construction which show templates depends of action name (contactus.tpl in this case)
5) in the end we show footer template
In such case we have flexible structure. All controllers should have index() functions and all controllers who can be called in content should have _show($act) function. Thats all.
In codeIgniter you can do that like this, you can load different views at the same time from your controller. for example:
for example in your navbar view you have a Contacts button in your menu that would look like this:
<a href='contacts'>Contacts</a>
In your controller:
public function contacts()
{
$this->load->view('header');
$this->load->view('navbar');
$this->load->view('sidebar');
$this->load->view('contacts_view');
$this->load->view('footer');
}
So we're assuming here that you have the following views already that is ready to be loaded (header.php, navbar.php, sidebar.php, contacts_view.php, footer.php).
UPDATE:
you don't need to have $_GET[] request, just provide the method name from your controller in the <a> anchor tag
in codeigniter i using template
first make template file in one folder with header.php, navbar.php, etc.
example : template.php
<?php
echo $this->load->view('header'); //load header
echo $this->load->view('navbar');//load navbar
echo $this->load->view('sidebar');//load sidebar
echo $this->load->view($body); //load dynamic content
echo $this->load->view('footer');//load footer
?>
second in controller
function index( ){
$data['body'] = 'home'; // cal your content
$this->load->view('template', $data);
}
How can I have multiple actions in my layout from different controllers/modules?
I tried this:
<div id="login"><?php $x=new User_LoginController; $x->LoginAction() ?>
<div id="news"><?php $x=new Site_NewsController; $x->ShowAction() ?>
You'll want to implement view helpers, specifically the placeholder() view helper.
For example to render a login form in any or all pages of your application, we start with a placholder for the form in our layout or view script:
<!--layout.phtml-->
<div>
<?php echo $this->layout()->login . "\n"?>
</div>
I use an action helper to prepare the form for display:
<?php
/**
* Prepares login form for display
*/
class My_Controller_Action_Helper_Login extends Zend_Controller_Action_Helper_Abstract
{
/**
* #return \Application_Form_Login
*/
public function direct()
{
$form = new Application_Form_Login();
//this is the url of the action this form will default too
$form->setAction('/index/login');
return $form;
}
}
now from any controller or front controller plugin the placeholder can be setup:
public function preDispatch()
{
$this->_helper->layout()->login = $this->_helper->login();
}
now the login form will display in any action from this controller that uses layout.phtml as it's layout. I'll let you discover plugins yourself.
Using helpers with placeholders would usually be the prefered way to accomplish what you want. However if you absolutely must display an action inside of anothers view you can use the Action view helper, just be aware that performance may suffer.
<div id="login">
<?php echo $this->action('login', 'login', 'user'); ?>
</div>
I didn't get what exactly you want?
What I guessed is may be you want to call this function(action) from layout to show what is
returning from there into layout......