what should i do to change this form field to be a range slider with percentage in laravel voyager
i dont know where to change the code in voyager, or maybe i should make a custom formfield?`<?php
namespace App\FormFields;
use TCG\Voyager\FormFields\AbstractHandler;
class NumberFormField extends AbstractHandler
{
protected $codename = 'number';
public function createContent($row, $dataType, $dataTypeContent, $options)
{
return view('formfields.number', [
'row' => $row,
'options' => $options,
'dataType' => $dataType,
'dataTypeContent' => $dataTypeContent
]);
}
}`
Related
I have written some code to upload a logo (picture) into a radio station using a crud table, the uploading function works when creating a new radio station, now I have made a update function for the same crud table using the following code in the controller:
public function update(Request $request, $id)
{
request()->validate([
'title' => 'required',
'url' => 'required',
'logo' => 'nullable',
]);
if ($request['logo'] === null) {
Internetradiostations::find($id)->update($request->all());
return redirect()->route('internetradiostationseditor.index')
->with('success','Internet radio station ge-updated');
} else {
$input['logo'] = time().'.'.$request->logo->getClientOriginalExtension();
$request->logo->move(public_path('logos'), $input['logo']);
$input['title'] = $request->title;
$input['url'] = $request->url;
Internetradiostations::find($id)->update($input);
return redirect()->route('internetradiostationseditor.index')
->with('success','Internet radio station ge-updated');
}
}
When executing the code I get the following error:
Call to a member function getClientOriginalExtension() on string
Anyone know how to solve this?, I have only changed create to update:
Internetradiostations::create($input);
To:
Internetradiostations::find($id)->update($input);
#Dmitry Thank you!, you were right, solved with changing the form opening of blade internetradiostationseditor.edit:
From:
{!! Form::model($internetradiostation, ['method' => 'PATCH','route' => ['internetradiostationseditor.update', $internetradiostation->id]]) !!}
To:
{!! Form::model($internetradiostation, ['method' => 'PATCH','route' => ['internetradiostationseditor.update', $internetradiostation->id], 'files'=>true, 'enctype'=>'multipart/form-data']) !!}
I am making a code using ASP.NET MVC with kendo grid.
I want to bring the data from database to Kendo grid which equal to specific date or by default "today".
I want to make a datepicker and a button at the toolbar and everytime I click the button it send a request to the control and filter the data in LINQ and send the request for all the data in one day. I wrote this code:
Controller class:
//main method
public ActionResult LogAdminList()
{
return View();
}
//submethod for grid
public ActionResult Grid_ReadLogAdminList([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "id")] string date)
{
DateTime _temp;
if (!DateTime.TryParse(date, out _temp))
_temp = DateTime.Now;
return Json(_context.Entities<LogAdmin>().NoTracking().OrderByDescending(l => l.TimeStamp)
.Where(f => DbFunctions.TruncateTime(f.TimeStamp) == DbFunctions.TruncateTime(_temp))
.Select(l => new LogAdminInfo
{
Id = l.Id,
Message = l.Message,
MessageTemplate = l.MessageTemplate,
Level = l.Level,
TimeStamp = l.TimeStamp,
Exception = l.Exception,
Properties = l.Properties,
LogEvent = l.LogEvent,
})
.ToDataSourceResult(request));
}
the kendo code is :
#(Html.Kendo().Grid<LogAdminInfo>()
.BindTo(Model)
.Name("LogAdminList")
.Sortable()
.Columns(columns =>
{
columns.Bound(p => p.Message).Width(50).Title(WebResources.LogListMessage);
columns.Bound(p => p.MessageTemplate).Width(50).Title(WebResources.LogListMessageTemplate);
columns.Bound(p => p.Level).Title(WebResources.LogListLevel);
columns.Bound(p => p.TimeStamp).Title(WebResources.LogListTimeStamp).Format("{0:dd.MM.yyyy H:mm}");
columns.Bound(p => p.Exception).Width(50).Title(WebResources.LogListException);
columns.Bound(p => p.Properties).Width(50).Title(WebResources.LogListProperties);
columns.Bound(p => p.LogEvent).Title(WebResources.LogListLogEvent);
})
.Pageable(pageable => pageable
.Refresh(true)
.ButtonCount(5))
.HtmlAttributes(new { #class = "grd_UpcomingMilestone" })
.ToolBar(toolbar =>
{
toolbar.Template(#<text>
<div class="toolbar">
<label class="category-label" for="category">#WebResources.LogFilterMessage</label>
#(Html.Kendo().DatePicker()
.Name("datepicker")
.Value(DateTime.Today)
.Format("dd.MM.yyyy")
)
#(Html.Kendo().Button()
.Name("filterButton")
.Icon("filter")
.Content("Filter")
.HtmlAttributes(new { type = "button" })
)
</div>
</text>);
})
.DataSource(source => source
.Ajax()
.Batch(true)
.ServerOperation(false)
.PageSize(100)
.Read(read => read.Action("Grid_ReadLogAdminList", "LogAdmin").Data("getFilterDate"))
))
I don't know what to do exactly in the javascript. the code works fine in the first request but not when I filter.
what should I write as a javascript?
thank you very much.
You have to pass data from client to server using getFilterDate function specified in you Kendo Grid Read Data method. Implement a function like this. The return type must be an object with fields with the same name you defined in your MVC Action, in this case date. Kendo will serialize them in order to build the get request:
function getFilterDate() {
var mydate = $("#datepicker").data("kendoDatePicker").value();
return {
"date": mydate
}
}
The following code works fine on development, but when we deploy to production the field fecha(initally datetime) gets null.
We even tried changing to string instead of datetime and it still doesnt work on our customer servers
Our partial view is like this:
fecha.chstml
#using xx.Relacionamiento.Modelo.Bussiness.Entities
#model EventoEducacionFecha
#using Kendo.Mvc.UI
<script type="text/javascript">
$(function () {
kendo.culture("es-CO");
})
function error_handler(e) {
if (e.errors) {
var message = "Errors:\n";
$.each(e.errors, function (key, value) {
if ('errors' in value) {
$.each(value.errors, function () {
message += this + "\n";
});
}
});
alert(message);
}
}
function getFecha() {
debugger
var fecha = $("#FechaEvent").val();
return {
FechaEvent: fecha
};
}
</script>
#(Html.Kendo().Grid<EventoEducacionFecha>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.EventoEducacionFechaId).Hidden();
columns.Bound(p => p.FechaEvent).Title("Fecha Evento").ClientTemplate("#= kendo.toString(kendo.parseDate(FechaEvent, 'yyyy-MM-dd'), 'MM/dd/yyyy') #");
columns.Bound(p => p.HoraInicio);
columns.Bound(p => p.HoraFin);
columns.Command(command =>
{
command.Edit().Text("Editar");
//command.Destroy();
command.Custom("Borrar").Click("openWindowConfirmDelete").HtmlAttributes(new { data_NomCol = "FechaEvent" });
}).Width(250).Title("Acciones");
})
.ToolBar(toolbar => toolbar.Create().Text("Agregar Fecha"))
.Editable(editable => editable.Mode(GridEditMode.InLine).DisplayDeleteConfirmation(false))
.Pageable()
.Sortable()
.Scrollable()
//.HtmlAttributes(new { style = "height:550px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Events(events => events.Error("error_handler"))
.Model(model =>
{
model.Id(p => p.EventoEducacionFechaId);
model.Field(a => a.EventoEducacionFechaId).Editable(false);
model.Field(a => a.FechaEvent).Editable(true);
model.Field(a => a.HoraInicio).Editable(true);
model.Field(a => a.HoraFin).Editable(true);
})
.Create(update => update.Action("Fechas_Create", "EventosEducacion").Data("getFecha"))
.Read(read => read.Action("GetFechas", "EventosEducacion").Data("getDatoEventoId"))
.Update(update => update.Action("Fecha_Update", "EventosEducacion"))
.Destroy(update => update.Action("Fecha_Destroy", "EventosEducacion"))
)
)
This is PART of the view that uses the partial view
<div class="row oculto" id="VerFecha">
<div class="col-md-12">
<div class="form-group">
<div id="mostrarFecha_div"></div>
#*#Html.Partial("~/Views/EventosEducacion/Fechas.cshtml",null,null)*#
</div>
</div>
And this is the controller action
//[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Fechas_Create([DataSourceRequest] DataSourceRequest request, EventoEducacionFecha EducaFecha, string FechaEvent)
{
if (EducaFecha.FechaEvent != null && EducaFecha.HoraInicio != null && EducaFecha.HoraFin != null)
{
LstEventoEducacionFecha.Add(new EventoEducacionFecha {
EventoEducacionFechaId = Guid.NewGuid(),
EventoId = Guid.Empty,
HoraFin = EducaFecha.HoraFin,
FechaEvent = DateTime.Parse(FechaEvent),
HoraInicio = EducaFecha.HoraInicio,
});
EducaFecha.EventoEducacionFechaId = LstEventoEducacionFecha.OrderBy(o => o.EventoEducacionFechaId).Select(s => s.EventoEducacionFechaId).FirstOrDefault();
return Json(new[] { EducaFecha }.ToDataSourceResult(request));
}
return Json(new[] { EducaFecha }.ToDataSourceResult(request));
}
In the past, I have had issues with Kendo's library and anything related to DateTime. You usually have to convert the DateTime that you are sending your controller from JavaScript's UTC time format to something that c# understands. Otherwise, send it as a string and see if it's still null or empty. I have a feeling it will send something over as a string and you can convert it on the server side.
In the past for a Kendo DateTime Picker, I have had to do the following client side in js:
var meetDatePicker = $("#MeetingDate").data("kendoDatePicker");
var mDate = new Date(meetDatePicker.value());
var meetDate = mDate.toUTCString();
Then pass the meetDate to my controller as a string, and on the server-side in c#:
DateTime meetDateConv = DateTime.Parse(meetingDate);
I have had similar problems, everything works fine on my side but on the client side things break. My solution is to check the Regional settings of the computer and check if the date format used is correct.
Your grid is bound to a EventoEducacionFecha model, which contains a FechaEvent field.
Your controller action is receiving the EventoEducacionFecha model AND a string called FechaEvent.
When the grid row is posted, the FechaEvent column value gets bound to the EventoEducacionFecha.FechaEvent field and is not bound to the separate FechaEvent string parameter as it has already been bound.
The model binder stops binding a posted value after the first match it finds and does not bind to all matching fields/parameters.
If you rename the FechaEvent field in getFecha() and rename the string parameter in your controller action to match, your should start getting a value.
I suppose the order of binding may be changed slightly between debug and release but I've not seen that personally...whenever I "duplicated" field/parameter names in my controller action, it has not worked in both configurations.
I have two entities: Issue and Notes, and an issue can have multiple notes. I defined them like this:
class Issue {
// ...
/**
* #ORM\OneToMany(targetEntity="Note", mappedBy="issue")
*/
protected $notes;
public function getNotes() {
return $this->notes->toArray();
}
public function addNote($note) {
if (!$this->notes->contains($note)) $this->notes->add($note);
}
public function removeNote($note) {
if ($this->notes->contains($note)) $this->notes->removeElement($note);
}
}
class Note {
// ...
/**
* #ORM\Column(type="string", nullable=false)
*/
protected $description;
/**
* #ORM\ManyToOne(targetEntity="Issue", inversedBy="notes")
* #ORM\JoinColumn(name="issue", referencedColumnName="id", nullable=false)
*/
protected $issue;
public function getDescription() // ...
public function setDescription() // ...
public function getIssue() // ...
public function setIssue() // ...
}
I defined an IssueType to create a form that embeds a NoteType form:
class IssueType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
// ...
->add('notes', 'collection', ['type' => new NoteType()]);
}
}
class NoteType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('description', 'textarea');
}
}
This works well when I want to create a new issue because the array of notes only contains one (blank) note created by the IssueController, which the user can fill in using the form. However, once the issue is created, I've got a view issue page that shows all the notes, and at the bottom there is a form to add a new note. The problem is that the collection form creates an input for a new (blank) note as well as for all the previous notes (see image below).
Is there any way I can only include the input for the new (blank) note form using Symfony, or do I need to remove the previous notes with JavaScript?
EDIT:
Here's the code for the IssueController:
public function newAction(Request $request) {
$em = $this->getDoctrine()->getManager();
$issue = new Issue();
$note = new Note();
$issue->addNote($note);
$note->setIssue($issue);
$form = $this->createForm('issue', $issue);
$form->handleRequest($request);
// ...
if ($form->isValid()) {
$em->persist($issue);
$em->persist($note);
$em->flush();
return $this->redirectToRoute(...);
}
return $this->render('/issue/new.html.twig', [
'issue' => $issue,
'form' => $form->createView()
]);
}
The note edit boxes appear because your form is instructing to create an editable collection for the one-to-many relationship. Putting something in a form type means it's typically going to be editable, or at the very least presented as form.
If you want your form to only be able to ADD a new note, you must remove that collection property of the form.
Instead of
->add('notes', 'collection', ['type' => new NoteType()]);
have
->add('newNote', 'textarea', ['label' => 'Add note', 'mapped' => false];
Your controller will need amendments too.
public function newAction(Request $request) {
$em = $this->getDoctrine()->getManager();
$issue = new Issue();
$form = $this->createForm('issue', $issue);
$form->handleRequest($request);
if ($form->isValid()) {
if ($newNote = trim($form['newNote']->getData())) {
$note = new Note();
$issue->addNote($note);
$note->setIssue($issue);
$note->setDescription($newNote);
$em->persist($note); // Probably not needed as you're cascading persist
}
$em->persist($issue);
$em->flush();
return $this->redirectToRoute(...);
}
return $this->render('/issue/new.html.twig', [
'issue' => $issue,
'form' => $form->createView()
]);
}
This will only show an input for a new note. To show existing notes you'll need to do this in your view, for example:
<h2>Notes</h2>
{% for note in issue.notes if note.description %}
<p>{{ loop.index }}: {{ note.description }}</p>
{% else %}
<p>No notes have been added for this issue.</p>
{% endfor %}
I have a kendo grid that is filtered by pushing values from a dropdownlist into the built in kendo filters. I can search the grid using the same method when I type values in a textbox and search. This is my kendo grid and the dropdown
#(Html.Kendo().DropDownListFor(model => model.MyObject.ID)
.Name("Objects").DataTextField("Value").DataValueField("Key")
.BindTo(#Model.MyObjectList).AutoBind(true)
.HtmlAttributes(new { id = "selectedObject" })
<a class="button" onclick="searchGrid()" id="search">Search</a>
#(Html.Kendo().Grid<MyViewModel>()
.Name("MyGrid").HtmlAttributes(new { style = " overflow-x:scroll;" })
.Columns(columns =>
{
columns.Bound(a => a.MyObject.Name).Title("Field 1");
columns.Bound(a => a.Column2).Title("Field 2");
}
.Pageable(page => page.PageSizes(true))
.Scrollable(src => src.Height("auto"))
.Sortable()
.Filterable()
.Reorderable(reorder => reorder.Columns(true))
.ColumnMenu()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Read(read => read.Action("GetList_Read", "MyController"))
)
)
<script>
function searchGrid()
{
selectedObject = $("#selectedObject").data("kendoDropDownList");
gridFilter = = { filters: [] };
if ($.trim(selectedRecipient).length > 0) {
gridListFilter.filters.push({ field: "Field 1", operator: "eq", value: selectedObject});
}
}
var grid = $("#MyGrid").data("kendoGrid");
grid.dataSource.filter(gridFilter);
</script>
My View model looks like
public class MyViewModel
{
public MyObject myObj {get;set;}
public string Column2 {get;set;}
}
The above function work when the search field is a textbox but it doesnt work when I am using a dropdown. I think it is because I am pushing the id of 'MyObject' into the grid filter while the grid is populated with the name of 'MyObject'. Can anyone show me how I can fix this. Thank you!!
There are two ways of handling this issue as I've found out. One is by pushing the selected values into the built in Kendo Filters or by passing a value to the controller action and filtering on the server side. First store the selected value of the dropdown on-change event to an object called 'selectedDropDownValue'
Filtering Client Side (Pushing values to kendo filters)
function searchGrid()
{
var gridListFilter = { filters: [] };
var gridDataSource = $("#MyGrid").data("kendoGrid").dataSource;
gridListFilter.logic = "and"; // a different logic 'or' can be selected
if ($.trim(selectedDropDownValue).length > 0) {
gridListFilter.filters.push({ field: "MyObject.MyObjectID", operator: "eq", value: parseInt(selectedDropDownValue) });
}
gridDataSource.filter(gridListFilter);
gridDataSource.read();
}
This pushes the selected value of the drop down to the built-in kendo grid filter
Filtering Server-side
Edit the DataSource read line by adding data
.Read(read => read.Action("GetApportionmentList_Read", "Apportionment").Data("AddFilter"))
Then create a javascript function to add the filter
function AddFilter()
{
return {filter:selectedDropDownValue};
}
Then inside the search grid JS function start with
function searchGrid()
{
var gridListFilter = { filters: [] };
var gridDataSource = $("#MyGrid").data("kendoGrid").dataSource;
gridDataSource.read();
}
After the read call you can still add client-side filters, apply the filter and then make the read recall afterwards.
The contoller signature should look like this
public JsonResult GetList_Read([DataSourceRequest] DataSourceRequest request, string filter)
filter will contain the value of the drop down selected
In your filter you are setting
value: selectedObject
but selectedObject is the actual Kendo DropDownList widget instance.
You need to get the value out of the widget using .value() or .text()
selectedObject = $("#selectedObject").data("kendoDropDownList").value();