How to create a Yii2 Html form and Action - yii2

I want to create a basic yii2 html with controller action just like below
<?= \yii\helpers\Html::beginForm('index.php?r=userprofile/changeusername','post') ?>
<div class="form-group">
<label for="inputsm">Change Username</label>
<?= Html::textInput('username'); ?>
<button type="submit" name="submit" class="btn btn-sm btn-theme">Change</button>
<?= Html::button('Press me!', ['class' => 'submit']) ?>
</div>
<?= \yii\helpers\Html::endForm() ?>
How to make a controller action for this

It's best to go to the WEB file and configure the Gii tool. (Or check).The Guide to GII: This link or in on this Page.
Then go to localhost/gii at localhost. or example.com/gii
if you have enabled pretty URLs, tutorial on this link
You can easily create models, form, controller and even CRUD and.. with Gii in yii2.
Yii includes a handy tool, named Gii, that provides rapid prototyping by generating commonly used code snippets as well as complete CRUD controllers.
Gii provides a Web-based interface for you to interactively generate the code you want. It also provides a command line interface for people who prefer to work with their console windows most of the time.
Controller for your view:
use Yii;
class UserprofileController extends yii\web\Controller
{
# code...
public function actionChangeusername()
{
# code...
if (Yii::$app->request->post()) {
# code...
return $this->redirect('path/...'); // sample ...
}
return $this->render('index', [
'param' => $var, /* sample: Access to variables in the view ... */
]);
}
//...
}
If you want to validate the form (via model ..), you should use activeTextInput
Also read about the following classes and widgets:
Model, ActiveRecord, ActiveForm , ActiveFiel
Validation rules (Adhoc ,Validating Input....)

Related

Split pjax wiget in form part and result part

I'm using Yii2, activeForm and the Yii2 pjax widget to handle an search form with result list.
But for layout reason, I have to split this package to two parts: the search form, which should be located in the header of the page and the result listing, which should be placed in the middle of the page.
This means it's not possible to do something like that (pseudocode):
Pjax::begin
$form=>activeForm::begin..
ActiveForm::end();
ListView::widget...
Pjax::end()
What I need is placing the activeForm in the layout header, placing the ListView wiget in the center of the page and telling pjax: read the input from the form, load data from Server and replace the clist view.
Is that possible using the build-in functionality of the widgets?
I didn't get it working, maybe I misunderstood the basic concept?
Using gridview (or widget which use searchModel) you could use a separated model for modelSearch in header and show the resul in the gridview palced where you prefer
in this way you need only a pjax block
<?= $this->render('_search', ['model' => $searchModel]); ?>
<?php Pjax::begin(); ?>
<?= GridView::widget([
...
]); ?>
<?php Pjax::end(); ?>
for other soluzione not based on gridview and when you need multiple seprataed pjax block
You could try using named pjax block using a value for id
<?php \yii\widgets\Pjax::begin(['id'=>'pjax-block1']); ?>
....
....
<?php \yii\widgets\Pjax::end(); ?>
<?php \yii\widgets\Pjax::begin(['id'=>'pjax-block2']); ?>
....
....
<?php \yii\widgets\Pjax::end(); ?>
and if you need you could manage specific refresh using jquery
$.pjax.reload({container: '#pjax-block1', async: false});
$.pjax.reload({container: '#pjax-block2', async: false});

.net mvc html help ActionLink and parameters to controller class

so simply want to make a button that will call the controller action passing a parameter...
have everything I believe in place but unable to configure/reference the parameter in the actionlink helper...
Yes I will be refactoring my button onclick once I get through this html helper setup...
<h1 style="font-size:30px">Enter The Core-i Product Key (format RST 102A08R EPCA 00007)</h1>
<form action="/action_page.php">
<label for="productKey">Product Key:</label>
<input type="text" id="productKey" name="productKey"><br><br>
</form>
<p>Click the "Get Key" button and a trial key will be generated custom to your IBMi hardware".</p>
<p>
#Html.ActionLink(
"Get Key",
"GetTrialKey", // controller action
"HomeController", // controller
new { productKey }, // IT DOES NOT LIKE PRODUCTKEY (REFERENCED ABOVE)
new { #class = "btn btn-info" }) // html attributes
</p>
<div class="display-2">
<a button class="text-center, btn btn-info form-control text-white" typeof="button" onclick="location.href='#Url.Action("GetTrialKey(productKey)")'">Get Key</button></a>
<p>
<br />
</p>
</div>
refactored to...
view...
<form action="HomeController/getTrialKey" method="POST">
<label for="productKey">Product Key:</label>
<input type="text" name="productKey" maxlength="22" value="xxx xxxxxxx xxxx xxxxx"><br><br>
<input type="submit" value="Get Trial Key" class="btn btn-primary" />
</form>
controller...
[HttpPost]
public async Task<IActionResult> getTrialKey(string productKey)
{
when I run it i get...
This localhost page can’t be foundNo webpage was found for the web address: https://localhost:44346/HomeController/getTrialKey
Referring back to one of the comments:
I didn't discourage you from using HTML Helpers. I just meant the way you constructed the form and you used ActionLink was wrong. And it would be easier to just have an input for the product key inside the form, if that's the only thing you want to post back to the server.
And I would highly recommend you to read through documentations from Microsoft, at least this one: https://dotnet.microsoft.com/apps/aspnet/mvc to understand what a MVC is. From your code sample, I didn't see you used M - Model at all.
Anyway, if you just only want to get the product key the user types in, I would do it like this:
Define a Controller
I dislike the idea of putting everything under /home (i.e., HomeController). Just think about the URL to the page that would make sense to the user.
Now I am guessing what you are trying to do. I saw terms like product keys and trial keys. What about a controller called ProductKeyController:
public class ProductKeyController : Controller
{
// This corresponds to /productkeys, and you can list all the product keys
// on the view it returns.
public ActionResult Index()
{
return View();
}
// This corresponds to /productkeys/create, and you can create a specific product
// key by asking the user to provide a trial key?
// The view this returns might be the page where you build the form
public ActionResult Create()
{
...
return View();
}
// This corresponds the form post.
[HttpPost]
public ActionResult Create(CreateProductKeyViewModel model)
{
...
return View(model);
}
}
The view model
Your MVC controller is responsible to fetch data, if needed, build a view model, and pass it to the view. When you create a product key, if you need to ask the user to enter anything, you can declare a model and properties within it:
public class CreateProductKeyViewModel
{
[Required]
[Display(Name = "Trial Key")]
[MaxLength(22)]
public string TrialKey { get; set; }
}
The View Create.cshtml
Since you know the controller will be passing the view model to the view, you can declare it on top of the view so that everything you do with the view model inside the view is strongly-typed.
#model CreateProductViewModel
#{
Layout = "xxx";
}
<h1>Enter The Core-i Product Key (format RST 102A08R EPCA 00007)</h1>
#using(Html.BeginForm("create", "productKey", new { area = "" }, FormMethod.Post))
{
#Html.LabelFor(x => x.TrialKey)
#Html.TextBoxFor(x => x.TrialKey)
<button type="submit">Create</button>
}
See how everything within the view is strongly-typed? You don't have to manually create the form and the input for asking user for the trial key.
And when the user enters the trial key and presses submit, it will post back to the Post method of Create. Since the view is declared with the view model, and the view model is the parameter of the create method, MVC has already done the model binding for you hence you will get what user entered on the post back.
This is at least something to get you started.
Note: I wrote everything by hand. Not tested.

Yii2 add to head() and endBody()

In developing a site that can have multiple front-end themes, I am looking for a way to allow users on the back-end to manually inject code into the head and body. Two use cases are as follows:
Case 1 - Styles
In the back-end, the user selects a theme.
User likes the theme but would like to make links a different color.
Rather than copy and modify the theme, user can set custom code to execute at end of <head> tag.
Case 2 - Scripts
User wants to add custom JavaScript to end of document but requires an additional JavaScript library as well.
Rather than copy and modify the theme, user can set custom code to execute at and of <body> tag.
I understand that both of these specific cases could be accomplished (in part) with the use of registerCss and registerJs but those automatically wrap whatever is passed to them in <style> or <script> tags. I am hoping there is a way to just directly inject whatever is indicated directly into the head() or endBody() methods. The reason behind this is that I do not wish to limit what the user can inject (perhaps a script tag is needed in the head).
Currently, I am just storing the code-to-be-added in params then manually including them in each theme as follows:
<?php $this->endBody() ?>
<?= $this->params['theme_include_body_end'] ?>
This is undesirable as it can easily be forgotten when creating the theme. I would like to find a way to append my param value to the endBody() call automatically so whenever endBody() is called, my code is included (same for the head() call).
Yii2 already provide this functionality in View Class by using Block Widget
you need 2 simple steps:
1- (in required View file): in any given view
<?php $this->beginBlock('block1'); ?>
...content of block1...
<?php $this->endBlock(); ?>
...
<?php $this->beginBlock('block3'); ?>
...content of block3...
<?php $this->endBlock(); ?>
2- (in layout): define block name and its place in the layout page
...
<?php if (isset($this->blocks['block1'])): ?>
<?= $this->blocks['block1'] ?>
<?php else: ?>
... default content for block1 ...
<?php endif; ?>
...
<?php if (isset($this->blocks['block2'])): ?>
<?= $this->blocks['block2'] ?>
<?php else: ?>
... default content for block2 ...
<?php endif; ?>
...
<?php if (isset($this->blocks['block3'])): ?>
<?= $this->blocks['block3'] ?>
<?php else: ?>
... default content for block3 ...
<?php endif; ?>
...
Referance: Yii2 Guide
http://www.yiiframework.com/doc-2.0/guide-structure-views.html#using-blocks
I hope this will help someone. Thank you.
You can use own View component that overrides methods renderHeadHtml() and renderBodyEndHtml(). In these methods can be injected necessary code as you need:
namespace common/components;
class View extends \yii\web\View {
/**
* #var string Content that should be injected to end of `<head>` tag
*/
public $injectToHead = '';
/**
* #var string Content that should be injected to end of `<body>` tag
*/
public $injectToBodyEnd = '';
/**
* #inheritdoc
*/
protected function renderHeadHtml()
{
return parent::renderHeadHtml() . $this->injectToHead;
}
/**
* #inheritdoc
*/
protected function renderBodyEndHtml($ajaxMode)
{
return parent::renderBodyEndHtml(ajaxMode) . $this->injectToBodyEnd;
}
}
In config file:
// ...
'components' => [
// ...
'view' => [
'class' => '\common\components\View',
]
]
Somewhere in controller code:
\Yii::$app->view->injectToHead = '...';
\Yii::$app->view->injectToBodyEnd = '...';
Another, perhaps more simple alternative depending on your use case is to use the view events. You can inject different items at different parts of the page. For example:
Yii::$app->view->on(View::EVENT_END_BODY, function () {
echo date('Y-m-d');
});
You can read more here: https://www.yiiframework.com/doc/guide/2.0/en/structure-views#view-events

MVC 5, Razor - How to create Edit Template for one property in model

I have a question that feels like it should be easy to answer, but I am not sure where to go with it.
I have several cshtml pages that take different models. But, each of these models has a common property, called WebSiteSK, and the same razor and Kendo UI code that handles that property in each cshtml file. What I want to do is extract this common razor and Kendo UI into an EditerTemplate.
So, I have one cshtml page that takes a Model, which I'll call ModelA. Then, another that takes another model, called ModelB. Both ModelA and ModelB have an integer property called WebSiteSK, which the code that I want extract into an editor template receives.
Here is the code that I want to centralize in an editor template:
<script type="text/x-kendo-tmpl" id="site-droplist-template">
<span>#: data.WebSiteSK # - </span>
<span><b>#: data.SiteName # </b> - </span>
<span>#: data.EnvironmentNK #</span>
<br />
<span>#: data.SiteUrl #</span>
</script>
<div>
#Html.LabelFor(model => model.WebSiteSK, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#(Html.Kendo().DropDownList()
.Name("WebSiteSK_Target")
.DataTextField("SiteName")
.DataValueField("WebSiteSK")
.DataSource(d => d.Read("GetWebSiteList", "Site"))
.Height(300)
.TemplateId("site-droplist-template")
.Filter("contains")
.OptionLabel("Select a site")
.Events(d =>
{
d.DataBound("onSiteBound");
d.Change("onSiteChange");
})
)
#Html.ValidationMessageFor(model => model.WebSiteSK, string.Empty, new { #class = "text-danger" })
</div>
</div>
Does that make sense? Can anyone help me do this?
You can create a base class that contains only the property 'WebSiteSK'. All models that have have this property then should inherit from this base class. Then you can create a partial view '_WebSiteSK' with the code that you want to reuse.
Your models:
public class MyModel : WebSiteSKBaseClass
The partial view must be typed with the base class
#model MyProject.Models.WebSiteSKBaseClass
Finally you can replace the replicated code in all views with:
#Html.Partial("_WebSiteSK")

Twig and CodeIgniter form rendering issue. Form is being displayed as a String and not the HTML form

My first time to use Twig template with CodeIgniter. I'm used to the default form functionality of the framework, but I was asked to try to render the form using Twig. I find the template engine to be nice and confusing at the same time. So that means, my controller would be very fat with code. But the main issue here is to render the form using twig.
Below is what I used to do when I want to render a form. View: TableSample.php
<?php
echo form_open("", array("name"=>"form_reg", "method"=>"post", "id"=>"form_reg"));
echo form_input("type"=>"text", "name"=>"fname", "value"=>set_value("fname"));
echo form_input("type"=>"text", "name"=>"lname", "value"=>set_value("lname"));
echo form_input("type"=>"text", "name"=>"emailaddress", "value"=>set_value("emailaddress"));
echo form_input("type"=>"submit", "name"=>"submit", "value"=>"Submit");
echo form_close();
?>
Controller: register.php
public function register (){
$this->load->view("TableSample");
if($this->input->post("submit")) {
/** retrieve input details, pass them as array to model, then redirect if registration is successful**/
}
}
But since I have to use Twig, things have been a little bit different.
public function register () {
$detail["form_open"] = form_open("", array("name"=>"form_reg", "method"=>"post", "id"=>"form_reg"));
$detail["form_input_name"] = form_input("type"=>"text", "name"=>"fname");
$detail["form_input_lname"] = form_input("type"=>"text", "name"=>"lname");
$detail["form_input_eadd"] = form_input("type"=>"text", "name"=>"email");
$detail["form_input_submit"] = form_input("type"=>"submit", "name"=>"submit", "value"=>"Submit");
$detail["form_close"] = form_close();
//codes for saving here
//call twig view
$this->twig->display("tableSample.html.twig", $detail);
}
tableSample.html.twig would be like this:
<html>
<head></head>
<body>
{{ form_open }} //will display form as a **String** and not THE **HTML** like this:
<form method="post" name="form_reg" id="form_reg"></form>
{{ form_close }}
</body>
</html>
I know I'm missing something, please point me to the right way of rendering this. Thank You!
ok, I think I got it. raw made it possible. Twig Raw Filter