I want to ask about custom widget in Yii2 advanced template - php

I have created a custom widget on my yii2 advanced project
I create new dir name components in backend dir
after that, I create new dir again in components dir name views
in backend/components I create new PHP file name SideBWidget.php
<?php
namespace backend\components;
use yii\base\Widget;
use yii\helpers\Html;
use common\models\Content;
class SideBWidget extends Widget{
public function run(){
$models = Content::findAll([
'c_pkey'=>0,
]);
$this->render('sideb',[
'model' => $models
]);
}
}
?>
in backend/components/views I create sideb.php
<div id="sidebar-nav" class="sidebar">
<div class="sidebar-scroll">
<nav>
<ul class="nav">
<?php foreach($model as $row): ?>
<li><i class="lnr lnr-alarm"></i> <span><?php echo $row->c_name; ?></span></li>
<?php endforeach; ?>
</ul>
</nav>
</div>
</div>
and I call the widget in views/layout/main.php like this, and I also use the widget path
use backend\components\SideBWidget;
<?= SideBWidget::widget() ?>
but when I run there is nothing and no error message. Where is the problem?

You must add return statement in run() function of widget:
return $this->render('sideb',[
'model' => $models
]);

Related

Render View inside a layout view in yii2

I need to make a search form, which will display on all pages, even the error pages, on the top of the page, so i decided to make a view and model for it, and render this view in the main layout.So i have created a simple model:
SearchModel.php
<?php
namespace app\models;
use Yii;
use yii\base\Model;
class SearchFormModel extends Model
{
public $query;
public function rules()
{
return [
];
}
}
And a view:
SearchView.php
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
$form = ActiveForm::begin([
'id' => 'search-nav-form',
'options' => ['class' => 'form-inline ml-3'],
]) ?>
<div class="input-group input-group-sm">
<?= $form->field($model, 'text')->textInput(['class' => 'form-control form-control-navbar', 'placeholder'
=> 'Search'])->label('Search'); ?>
<div class="input-group-append">
<button class="btn btn-navbar" type="submit">
<i class="fa fa-search"></i>
</button>
</div>
</div>
<?php ActiveForm::end() ?>
Which is a search form. Now i have also the main layout:
<?php
use app\widgets\Alert;
use yii\helpers\Html;
use yii\bootstrap\Nav;
use yii\bootstrap\NavBar;
use yii\widgets\Breadcrumbs;
use app\assets\AppAsset;
AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>">
<head>
<meta charset="<?= Yii::$app->charset ?>">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php $this->registerCsrfMetaTags() ?>
<title><?= Html::encode($this->title) ?></title>
<?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>
<div class="wrap">
<div class="container">
<?= Breadcrumbs::widget([
'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
]) ?>
<?= Alert::widget() ?>
<?= $content ?>
</div>
</div>
<footer class="footer">
<div class="container">
<p class="pull-left">© My Company <?= date('Y') ?></p>
<p class="pull-right"><?= Yii::powered() ?></p>
</div>
</footer>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>
What i dont understand is, how i can render my search form from inside my layout view? I need to put it in controller, but controller only gives actions for specific page routes.
UPDATE
I got rid of all errors but now the form is just not rendering on the page, there is no form tag even. Here is how i render it inside main.php:
$model = new SearchFormModel;
$this->render('#app/views/site/SearchFormView',['model' => $model]);
And i have fixed the model SearchFormModel.php like this:
class SearchFormModel extends Model
{
public $search;
public function rules()
{
return [
// тут определяются правила валидации
];
}
}
You can render a view inside a layout file using
<?= $this->render('//layouts/path/to/view') ?>
<?= $this->render('#app/views/path/to/view') ?>
or
<?= Yii::$app->view->renderFile('#app/views/path/to/view.php'); ?>
See DOCS for render() and renderFile()
Render function in Yii2 returns the result of rendering. You have to echo explicitly. Try out instead:
$model = new SearchFormModel;
echo $this->render('#app/views/site/SearchFormView',['model' => $model]);
You should extract your form into widget and use it in your layout. Layouts should be relatively simple, including some external view into it looks like code smell, and creating model inside of view file (including layouts files) is basically a violation of MVP pattern.
Create widget with form:
class SearchFormWidget extends \yii\base\Widget {
public function run() {
$model = new SearchFormModel();
$model->load(Yii::$app->request->get());
return $this->render('search-form-widget', ['model' => $model]);
}
}
Put view with your form in widgets/views/search-form-widget.php (or similar path depending where you put widget class), and use widget inside of layout:
<?= SearchFormWidget::widget() ?>
In similar way you may use it in any other place. Much more clean and safe approach than including views viles directly.

dynamically loading content codeigniter

I have this html code
<body>
<div class="wrapper">
<div class="banner">
</div>
<div class="nav_bar">
<ul>
<li>Home</li>
<li>News</li>
<li>Registration FAQs</li>
<li>How to Register and Rules</li>
<li>Register school</li>
<li>Register pupil</li>
<li>About Us</li>
<li>Contact Us</li>
</ul>
</div>
<div class="content_area">
**<?php echo $content; ?>**
</div>
<div class="clear"></div>
</div>
<div class="footer">
<div>
</div>
</div>
</body>
now once the user clicks the links i want to load the content depending on which link he has clicked as you can see inn the code above. I can load the content as long as its all html but now that php tags are included i find it hard. how do i load the content with the following data?
<div id="form_input">
<?php
echo form_open('form/data_submitted');
// Show Name Field in View Page
echo form_label('User Name :', 'u_name');
$data= array(
'name' => 'u_name',
'placeholder' => 'Please Enter User Name',
'class' => 'input_box'
);
echo form_input($data);
// Show Email Field in View Page
echo form_label('User email:', 'u_email');
$data= array(
'type' => 'email',
'name' => 'u_email',
'placeholder' => 'Please Enter Email Address',
'class' => 'input_box'
);
echo form_input($data);
?>
</div>
// Close Form
<?php echo form_close();?>
is it possible?
I would suggest the following:
Your Controller:
class Site extends CI_Controller
{
public function home()
{
$arrViewData = array
(
"content" = $this->load->view("site/home","",true)
);
$this->load->view("index", $arrViewData);
}
}
your view called i.e. index
<html>
<body>
<div class="wrapper">
<div class="banner">
</div>
<div class="nav_bar">
<ul>
<li>Home</li>
<li>News</li>
<li>Registration FAQs</li>
<li>How to Register and Rules</li>
<li>Register school</li>
<li>Register pupil</li>
<li>About Us</li>
<li>Contact Us</li>
</ul>
</div>
<div class="content_area">
<?= $content; ?>
</div>
<div class="clear"></div>
</div>
<div class="footer">
<div>
</div>
</div>
</body>
</html>
your view called home.php in views/site/
hello i'm home
with this method i think you can achieve what you want if i understand you correctly
as a side note: this is an example - but you should be able to see the point
You might want to consider breaking your view html into a smaller "snippets". CodeIgniter (CI) makes it easy to load them in the order you want and then "show" them all at once.
One possible breakdown of views into snippets follows.
header_view.php
<!DOCTYPE HTML>
<html>
<head>
<title>
<?= (isset($page_title)) ? $page_title : "Rapids Riders"; ?>
</title>
In the next view snippet I put some URLs in the links to serve as examples using the CI controller/function syntax. Adjust to your needs. To my thinking "home", "news" and "register" are separate controllers. I will focus on the Registration controller in a bit.
If you're not familiar with <?= it is shorthand for <?php echo.
body_start_view.php
<body>
<div class="wrapper">
<div class="banner">
</div>
<div class="nav_bar">
<ul>
<li><a href=<?= base_url("home"); ?>>Home</a></li>
<li><a href=<?= base_url("news"); ?>>News</a></li>
<li><a href=<?= base_url("register/faq"); ?>>Registration FAQs</a></li>
<li><a href=<?= base_url("register/help"); ?>>How to Register and Rules</a></li>
<li><a href=<?= base_url("register/school"); ?>>Register school</a></li>
<li><a href=<?= base_url("register/pupil"); ?>>Register pupil</a></li>
<li><a href=<?= base_url("home/about"); ?>>About Us</a></li>
<li><a href=<?= base_url("home/contact"); ?>>Contact Us</a></li>
</ul>
</div>
footer_view.php
<div class="clear"></div>
</div>
<div class="footer">
<div>
</div>
</div>
</body>
</html>
These three view snippets are easily reused by any controller on the website. A controller based "helper" function is shown below (in the registration controller) to demonstrate implementing a sort of "templating" scheme.
The example form html will be in a file called pupil_form_view.php and would be used (in my example) for the register/pupil page.
When using an MVC app structure you typically want to set as much "data" as possible in the controller and then pass it to the view. The various vars in this file will be defined and set in the controller calling this view.
pupil_form_view.php
<div id = "form_input">
<?php
echo form_open($form_action);
// Show Name Field in View Page
echo form_label($name_field['label'], $name_field['name']);
echo form_input($name_field);
// Show Email Field in View Page
echo form_label($email_field['label'], $email_field['name']);
echo form_input($email_field);
?>
</div>
// Close Form
<?php echo form_close(); ?>
Register.php is a controller that handles multiple pages - faq, help, school, pupil
class Register extends CI_Controller
{
function __construct()
{
parent::__construct();
}
//pupil will show the pupil registration form
public function pupil()
{
$view_file = "pupil_form_view"; //the file name of a view to load
$data['page_title'] = "Pupil Registration";
$data['form_action'] = 'form/data_submitted';
//form fields info
$data['name_field'] = array(
'label' => 'User Name: ',
'name' => 'u_name',
'placeholder' => 'Please Enter User Name',
'class' => 'input_box'
);
$data['email_field'] = array(
'type' => 'email',
'name' => 'u_email',
'placeholder' => 'Please Enter Email Address',
'class' => 'input_box'
);
//output a page
$this->render_page($view_file, $data);
}
//This function handles all the repetitive view loading code.
//Just pass it the name of a view file and some data to use in the views
//The default value for $view_data means you don't HAVE TO pass this argument if not needed
protected function render_page($content, $view_data = NULL)
{
//notice the use of 'method chaining' for load functions
$this->load
->view('header_view', $view_data)
->view('body_start_view')
->view($content) //$view_data vars will be visible to this view file
->view('footer_view');
}
public function faq()
{
$data['page_title'] = "Frequently Asked Questions";
$view_file = "faq_view";
//other data setting code if needed
$this->render_page($view_file, $data);
}
public function school()
{
$data['page_title'] = "School Registration";
$view_file = "school_form_view";
//other data setting code
$this->render_page($view_file, $data);
}
public function help()
{
$data['page_title'] = "How to Register";
$view_file = "help_view";
//other data setting code
$this->render_page($view_file, $data);
}
function index()
{
//just load the help page when users navigate to example.com/register
$this->help();
}
}
I know I went overboard here. Hope this is useful.
I solved it by nesting views that is calling $this->load->view($content); within my template view instead of <?php echo $content;?> then on the controller function i loaded the content like this
$data['content']='view_name_here'; // this loads content with a view
$this->load->view('my_template',$data); //loaded my template with $content

Yii Submit Form in View page

I just started working with yii and I stumbled upon a problem.
I have a table called "users" and a table called "messages".
I basically want to have a page where I can view a user's details but also send him a message that would be saved in the message table.
I have a view called "user/view.php" which consists of:
<h1>View User #<?php echo $model->id; ?></h1>
<?php $this->widget('zii.widgets.CDetailView', array(
'data'=>$model,
'attributes'=>array(
'id',
'username',
'first_name',
'last_name',
),
)); ?>
<?php $message=new Message;
echo $this->renderPartial('_messagesend', array('model'=>$message)); ?>
the _messagesend form (created using gii) looks like:
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'message-_messagesend-form',
'enableAjaxValidation'=>false,
)); ?>
<p class="note">Fields with <span class="required">*</span> are required.</p>
<?php echo $form->errorSummary($model); ?>
//for the sake of simplicity lets just insert the id's manually for now
<div class="row">
<?php echo $form->labelEx($model,'idFrom'); ?>
<?php echo $form->textField($model,'idFrom'); ?>
<?php echo $form->error($model,'idFrom'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'idTo'); ?>
<?php echo $form->textField($model,'idTo'); ?>
<?php echo $form->error($model,'idTo'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'msg'); ?>
<?php echo $form->textField($model,'msg'); ?>
<?php echo $form->error($model,'msg'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton('Send'); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
I have a simple view in my UserController to display the details info:
public function actionView($id)
{
$this->render('view',array(
'model'=>$this->loadModel($id)
));
}
And now I want to figure out how i can add the controller to save the message. After gii creation I get a code which I tried to use and modify a little bit:
public function actionMessagesend()
{
$model=new Message;
if(isset($_POST['Message']))
{
$model->attributes=$_POST['Message'];
if($model->save()){
$this->redirect(array('admin'));
}
}
$this->render('_messagesend',array('model'=>$model));
}
I tried to add this controller function in the UserController.php but it doesn't seem to work, I tried to add the same function to MessageController.php but it also doesn't seem to work. I tried to remove all the code and only add a redirect to show if the controllercode actually hits but it doesn't redirect (i tried it both in usercontroller and messagecontroller). So I have a feeling my code isn't reached. You guys have any idea what I'm missing here?
Maybe a little extra question: Is there a better suggestion to do what I want to do?
Thanks a lot!
Best regards,
WtFudgE
Your message sending action isn't reached because by default the CActiveForm submits to the current page, so you will have to add the message processing to the view action, or you will need to set the action property for your CActiveForm.
Here is the link to the property documentation: http://www.yiiframework.com/doc/api/1.1/CActiveForm#action-detail
So the form widget in the view should be something like:
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'message-_messagesend-form',
'enableAjaxValidation'=>false,
'action' => array( '/message/messageSend' ), // change depending on your project
)); ?>
You can also achieve this by editing the submit button in the view page like this:
<?php echo CHtml::button('Send', array('submit' => array('message/messageSend')));?>

Display two views at once and change url on change

I have a main view with a menu which helps me display another view. It's similar to this:
<div id="page">
<div id="menu">
Page1
Page2
</div>
<div id="content">
<!-- Page1 or Page2 are displayed here -->
</div>
</div>
I'm using php's Yii framework. Which makes me not to use <?php include("menuview.php"); ?>. So I'm looking for a different solution. I can do this with Ajax, but I would also like the link to change to mypage/controller/Page2. With Ajax I can only get it to this: mypage/controller/index#Page2
in main view, instead of include do
<?php echo $this->renderPartial('_page1', array('model'=>$model)); ?>
UPDATE:
protected/views/controller/page1.php and protected/views/controller/page2.php content at your liking
protected/views/layouts/custom.php:
<?php $this->beginContent('//layouts/main'); ?>
<div id="page">
<div id="menu">
<?php echo CHtml::ajaxLink('Page1', array('controller/page1'), array('update' => '#content')); ?>
<?php echo CHtml::ajaxLink('Page2', array('controller/page2'), array('update' => '#content')); ?>
</div>
<div id="content">
<?php echo $content; ?>
</div>
</div>
<?php $this->endContent(); ?>
protected/controllers/ControllerController.php:
class ControllerController extends Controller {
/**
* #var string the default layout for the views.
*/
public $layout = '//layouts/custom';
public function actionPage1() {
if (Yii::app()->request->isAjaxRequest)
$this->renderPartial('page1');
else
$this->render('page1');
}
public function actionPage2() {
if (Yii::app()->request->isAjaxRequest)
$this->renderPartial('page2');
else
$this->render('page2');
}
}
UPDATE2:
If you need the link in address bar to change too then your only option is to use regular link and not ajax <?php echo CHtml::link('Page1', array('controller/page1')); ?>
using ajax the preferred way is using hash like you mentioned.

Displaying another controller's view inside a view

I'm using cakephp and I want the login view for the controller 'users' to be displayed on the default.ctp for the layout controller. I can I do this?
For example:
<div id="leftNav">
<div id="login-block" class="block">
<?php
//render users/login here
?>
<ul>
<li>Login</li>
<li>Register</li>
<li>Logout</li>
</ul>
</div>
</div>
I would make it an element - they are designed for re-usable code chunks that can be used anywhere.
To summarize the functionality, in your view you'd use:
<?php echo $this->element('login'); ?>
and put your "login-block" div login stuff in
/app/views/elements/login.ctp
If you don't use elements for that and you already have the login view you can use it like this
<?php echo $this->requestAction('/users/login'); ?>

Categories