I have a Helper as the following:
class IconHelper extends Helper{
public function showList(){
//render a template from ctp file
$template = loadFromTemplate('path/to/my.ctp');
}
}
I want a function to render a .ctp template and return it .
I found View Cells:
In the case that your content can is small inline template, then you can use the Helper, as following:
class IconHelper extends Helper{
public function show($icon){
$template = '<a class="btn btn-default">'.$icon.'</a>';
return $template
}
but in the case when the content is saved in a template CTP file, the best practice is to use the View Cells:
//helper class
class IconListCell extends Cell{
public function display($icon){
//script .....
$this->set(copmat('icon));
}
}
//file: src/Template/Cell/show.ctp
<a class="btn btn-default" style="font-size: 40px;width: 70px;">
<span class="'.$icon.'" id="icon-value-button" data-pack="default">/span>
</a>
Related
My angular component has a tree and several nodes. When I double click on a node the click event runs a web api and retrieves data for an id that will be used to create a dynamic form using npm package: #rxweb/reactive-dynamic-forms. Once the data request is 'completed' a button appears and when clicked it opens the form with appropriate fields for the id selected. I would like to eliminate the need for this secondary button click. I've tried several suggestions but just cannot get anything to work.
I'm using Infragistics controls and bootstrap for the form.
html:
<div class="column-layout my-pane-layout">
<div *ngIf = "isShowFormButton" >
<button #open igxButton="raised" igxRipple="white" (click)="form.open()">Run</button>
<igx-dialog #form [closeOnOutsideSelect]="true" >
<igx-dialog-title>
<div class="dialog-container">
<igx-icon>vpn_key</igx-icon>
<div class="dialog-title">Form</div>
</div>
</igx-dialog-title>
<form class="input-group-form" [formGroup]="dynamicForm.formGroup" (ngSubmit)="onSubmit()">
<div class="container">
<div class="controls" viewMode="horizontal" [rxwebDynamicForm]="dynamicForm" [uiBindings]="uiBindings">
</div>
<button igxButton="raised" type="submit" igxRipple class="button" [disabled]="!dynamicForm.formGroup.valid">
<igx-icon>
directions_run
</igx-icon>
<span>Submit</span>
</button>
</div>
</form>
<div igxDialogActions>
<!-- <button igxButton (click)="form.close()">CANCEL</button> -->
<button igxButton (click)="form.close()">Submit</button>
</div>
</igx-dialog>
</div>
<h6 class="h6">
Levels
</h6>
<igx-tree #tree class="tree" selection="None" >
<igx-tree-node *ngFor="let level1 of myData" [data]="level1">
{{ level1.Name }}
<igx-tree-node *ngFor="let level2 of level1.levels" [data]="level2">
{{ level2.Name }}
<igx-tree-node *ngFor="let level3 of level2.levelplus" [data]="level3" (dblclick)="onDoubleClick($event,level3)">
{{level3.Name }}
</igx-tree-node>
</igx-tree-node>
</igx-tree-node>
</igx-tree>
</div>
XYZ.component.ts:
export class XYZComponent implements OnInit {
#ViewChild('form') dialog: IgxDialogComponent;
myData: any[];
public tree: IgxTreeComponent;
public selectedNode;
public ID: number = 2;
isShowRunButton: boolean = false;
public dynamicForm!: DynamicFormBuildConfig;
public dynamicFormConfiguration!: DynamicFormConfiguration;
constructor(private dynamicFormBuilder:RxDynamicFormBuilder){}
ngOnInit() {
populate tree with data here ...
}
public onDoubleClick(event,node) {
console.log(node);
event.stopPropagation();
this.runParameters(node.Id);
}
public runParameters(Id) {
this.aSer.getApi(Id).subscribe({next:(data: any[]) => {this.myData = data;},
error: err => {console.log(err); },
complete: () => {
this.dynamicForm =
this.dynamicFormBuilder.formGroup(this.myData,this.dynamicFormConfiguration);
this.isShowFormButton = true;
//this.dialog.open();
}
});
}
public onSubmit() {
console.log(this.dynamicForm.formGroup);
this.isShowFormButton= false;
//this.dialog.open();
}
}
If I uncomment out the 'this.dialog.open()' the code throws the following error:
TypeError: Cannot read properties of undefined (reading 'open')
Many postings say that I need to use a #ViewChild but it seems that it cannot find that reference : #ViewChild('form') dialog: IgxDialogComponent;
Any help would be much appreciated. Code works fine with the 'Run' button click but I want to eliminate that extra step.
Inside a normal View, we are populating a table via the model with this:
#foreach (var item in Model)
{
if (item.PartnerSubscriptionID > 0)
{
<tr id='customlistid_#item.CustomList.ListID'>
<td>
<button type="button" class="btn btn-secondary" onclick='ListCustomEdit("#item.CustomList.ListID")'>
<i class='fas fa-users'></i>
</button>
</td>
<td style="display:none">#Html.DisplayFor(modelItem => item.CustomList.ListID)</td>
<td style="text-align:left">#Html.DisplayFor(modelItem => item.CustomList.ListName)</td>
<td><button id='btnDelete' type='button' class='btn btn-danger' onclick='ListCustomDeleteConfirm(" #item.CustomList.ListID ")'><i class='fas fa-trash'></i></button></td>
</tr>
}
}
On the same page I have a View Component. It works when I hard code the ListID like this:
<div class="col-8">
#await Component.InvokeAsync("ListCustomMembers" , new {ListID = 7 } )
</div>
But we need the ID to be passed in when the user clicks the row. Ie, where we currently have the onclick=ListCustomEdit() we need to refresh the View Component with the correct ID.
How do I do it?
ViewComponent is rendered on the server side, so when the user clicks in the browser, you need to send another request to the server to render and return the ViewComponent with the new parameter, for which you can use a controller.
Create an action in the controller you want to return the ViewComponent, then update the view as shown below after clicking the button using jquery
public class TestController : Controller
{
public IActionResult GetNewList(int listId)
{
return ViewComponent("ListCustomMembers", new { listId });
}
}
on the view side:
<button type="button" class="btn btn-secondary" onclick='ListCustomEdit("#item.CustomList.ListID")'>
<div class="col-8" id="ListCustomMembers">
#await Component.InvokeAsync("ListCustomMembers" , new {ListID = 7 } )
</div>
<script>
function ListCustomEdit(listId) {
$.get('/test/GetNewList/?listId=' + listId,
function(result) {
$("#ListCustomMembers").html(result);
});
}
</script>
I have two tables branch and roadname each branch have many roadnames. I need to add this roadname on the selected branch. One branch can have multiple roads. I am not able to insert the values please guide me through.
Table branch:
enter image description here
Roadname
enter image description here
Here is my code:
Blade
#section('content');
<div class="content-wrapper">
<form id="roadnames" action="{{route('addroad',[$branch[0]->id])}}" method="POST">
<input type = "hidden" name = "_token" value = "<?php echo csrf_token(); ?>">
<table id ="add">
<tr>
<thead>
<th>RoadName</th>
</thead>
</tr>
<tbody>
<tr>
<td><input type="text" class="form-control" name="roads[]" id="road"></td>
</tr>
</tbody>
</table>
<button id="add_road" class="btn btn-primary"> Add More</button>
<input type="submit" name="submit" class="submit action-button" value="Submit"/>
</form>
</div>
<script type="text/javascript">
$(document).ready(function(){
$("#add_road").on("click", function(){
$('#add tr:last').clone().appendTo('#add');
});
});
</script>
#endsection
Controller
public function addroads(Request $request,$id)
{
$resultset = DB::select('select * from table_branch where id = ?',[$id]);
$roadname = $request->input('roads');
$branch_id = $id;
$arr = array($roadname,$branch_id);
if(DB::table('roadname')->insert($arr))
{
echo "Records inserted";
}
else
{
echo "Records not inserted";
}
return view('addroads',array('branch'=>$resultset));
}
Routes
Route::get('/admin/road/addrecord/{id}', '\App\Http\Controllers\AdminController#addroads')->name('addroad');
I suggest you to create models for each table using php artisan command.Models help you to write relationship and keep your code clean ,also it will quicker compare to db queries
For example php artisan make:model Branch
Branch Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Branch extends Model
{
use HasFactory;
protected $table="table_branch";
protected $guarded=['id'];
public function roadName(){
return $this->hasMany(RoadName::class);
}
}
RoadName model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class RoadName extends Model
{
use HasFactory;
protected $table="roadname";
protected $guarded=['id'];
}
In your controller
$branch=\App\Models\Branch::query()->find($id);
$roadName=[];
if(isset($request->roads)&&count($request->roads)){
foreach ($request->roads as $value){
$roadName[]=new \App\Models\RoadName(['roadname' => $value]);
}
$branch->roadName()->saveMany($roadName);
}
Note: this created using laravel 8.
You can learn more about in official documentation
Ref:https://laravel.com/docs/8.x/eloquent-relationships#one-to-many
I want to include data (fetching from a database) in the _layout file of my asp.net mvc core project.
Situation:
_Layout page
#if (SignInManager.IsSignedIn(User))
{
Html.Action("Modules", "Layout")
}
Controllers/LayoutController.cs
using Microsoft.AspNetCore.Mvc;
namespace project.Controllers
{
public class LayoutController : Controller
{
...
public ActionResult Modules()
{
///Return all the modules
return PartialView("_Modules", moduleAccess.ToList());
}
}
}
Views/Shared/_Modules.cshtml
#model IEnumerable<project.Models.Module>
<div class="two wide column">
<div class="ui menu" id="modules">
#foreach (var item in Model)
{
<a class="item">
#Html.DisplayFor(modelItem => item.Name)
</a>
}
</div>
When going the webpage I get the following error:
'IHtmlHelper<dynamic>' does not contain a definition for 'Action' and the best extension method overload 'UrlHelperExtensions.Action(IUrlHelper, string, object)' requires a receiver of type 'IUrlHelper'
What am I doing wrong? How can I get the data in the layout page?
In ASP.NET Core instead of Html.Action use View Components: #await Component.InvoceAsync.
You can still use #await Html.RenderPariantAsync and pass there some data from the model if you want.
Solution with view components
ViewComponents/ModuleListViewComponent.cs
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
namespace ViewComponents
{
public class ModuleListViewComponent : ViewComponent
{
...
public async Task<IViewComponentResult> InvokeAsync()
{
return View(moduleAccess.ToList());
}
}
}
Views/Shared/Components/ModuleList/Default.cshtml
#model IEnumerable<project.Models.AdminModels.Module>
<div class="two wide column">
<div class="ui left vertical labeled icon menu stackable" id="modules">
#foreach (var module in Model)
{
<a class="item">
#module.Name
</a>
}
</div>
</div>
Views/Shared/_Layout.cshtml
#if (SignInManager.IsSignedIn(User))
{
#await Component.InvokeAsync("ModuleList")
}
I'd like to customize the inputSubmit template. I would like a template like that:
<button class="btn waves-effect waves-light" type="submit" name="action">Submit
<i class="mdi-content-send right"></i>
</button>
For the moment I do that:
'inputSubmit' => '<button type="{{type}}" class="btn waves-effect waves-light" {{attrs}}>Submit<i class="mdi-content-send right"></i>'
It's working but I'd like to customize the text directly in the view template.
How can I do that ?
Thank you in advance :)
The input function allows you to override templates on the fly:
$this->Form->input('name', ['templates' => ['inputContainer' => '...']]);
Additionally, The create function also allows to override the templates for all inputs inside that form:
$this->Form->create($entity, ['templates' => ['inputContainer' => '...']]);
In my case I've made CustomFormHelper, which extends the FormHelper and overrides the template. As in example below.
class CustomFormHelper extends FormHelper
{
public function __construct(View $View, array $config = []) {
$this->_defaultConfig['templates']['inputContainer'] = '<div class="test">{{content}}</div>';
parent::__construct($View, $config);
}
}