I need to have a start and end time widget on a form.
i.e. the user selects a date and then selects the start and end time.
In the standard date widget, you can select a date and a time, however I need to be able to select a finish time too.
Have any of you done it before?
I could create 3 separate widgets:
Date
Start Time
End Time
When the form is saved, I'll do an update on the object to combine all values into one. For example, I'll get the date and add the start time to it and then save to the field "start_date" and then I'll get the date and add the end time to it and then save to the field "end_date". It does however seem a very long winded way to do something which should be fairly trivial for a form framework.
Is this how you'd do it? Thanks guys!
I think what you want to want achieve with symfony forms is pretty easy. You are right, you need three separate widgets and three separate validators, there isn't an out of the box solution for this exact situation.
In your form configure method you would have something like:
$this->setWidgets(array(
'date' => new sfWidgetFormDate(),
'time_start' => new sfWidgetFormTime(array('label' => 'Start Time', 'with_seconds' => false)),
'time_finish' => new sfWidgetFormTime(array('label' => 'End Time', 'with_seconds' => false)
));
$this->setValidators(array(
'date' => new sfValidatorDate(), // by default outputs in format Y-m-d
'time_start' => new sfValidatorTime(), // by default outputs in format H:i:s
'time_finish' => new sfValidatorTime(),
));
Let's assume that the object has two properties, as you suggested, both are datetime fields.
In your action you would have something like the following to set the datetime fields:
$values = $this->form->getValues();
$object->setStartDateTime(sprintf('%s %s', $values['date'], $values['time_start']));
$object->setFinishDateTime(sprintf('%s %s', $values['date'], $value['time_finish']));
Edit: another suggestion is not use the built in time widget sfWidgetFormTime as it can look pretty ugly. You can simply use a normal text box (centre aligned, with maxlength=5), and the sfValidatorTime validator will still work perfectly.
Hope that helps.
Your requirement sounds application-specific and not really something the Symfony form framework would help you with out-of-the-box.
I would go with your suggestion of generating start_date and end_date from the output of the three widgets, or if your application needs to return date, start_time and end_time separately later, then possibly just save three values separately and manipulate them when queried.
So, I've done the code for it and it works very well. I've removed all the unnecessary widgets and validators. Here is how I did it:
class VisitForm extends BaseVisitForm
{
private function getMinutes()
{
$minutes = array();
for($i = 0; $i < 60; $i = $i + 5)
{
$minutes[$i] = sprintf('%02d', $i);
}
return $minutes;
}
public function configure()
{
$this->setWidgets(array(
'id' => new sfWidgetFormInputHidden(),
'date' => new sfWidgetFormJQueryDate(array('date_widget' => new sfWidgetFormDate(array('years' => $years, 'can_be_empty'=> false)), 'image' => '/images/icons/calendar.png', 'format'=>'%day%/%month%/%year%')),
'start_time' => new sfWidgetFormTime(array('with_seconds' => false,'can_be_empty'=> false, 'default' => '08:00', 'minutes'=> array_combine($this->getMinutes(), $this->getMinutes()))),
'end_time' => new sfWidgetFormTime(array('with_seconds' => false,'can_be_empty'=> false, 'default' => '08:00', 'minutes'=> array_combine($this->getMinutes(), $this->getMinutes())))
));
$this->setValidators(array(
'start_time' => new sfValidatorTime(),
'end_time' => new sfValidatorTime(),
'date' => new sfValidatorDate(),
));
$this->widgetSchema->setNameFormat('visit[%s]');
$this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema);
}
protected function doUpdateObject($values)
{
$this->getObject()->setStartDate(sprintf("%s %s", $values['date'], $values['start_time']));
$this->getObject()->setEndDate(sprintf("%s %s", $values['date'], $values['end_time']));
parent::doUpdateObject($values);
}
public function updateDefaultsFromObject()
{
if(!$this->getObject()->isNew())
{
$this->setDefault('date', $this->getObject()->getDateTimeObject('start_date')->format('Y-m-d'));
$this->setDefault('start_time', $this->getObject()->getDateTimeObject('start_date')->format('H:i'));
$this->setDefault('end_time', $this->getObject()->getDateTimeObject('end_date')->format('H:i'));
}
parent::updateDefaultsFromObject();
}
}
Related
I am wanting to do a date of birth composite drop-down for date of birth (i.e. three drop-downs - one for day, one for month, one for year). Helpfully, ZF2 comes with this element built in, called DateSelect
Here is how I am adding it to the form:
$this->add([
'name' => 'date_of_birth',
'type' => 'DateSelect',
'attributes' => [
'required' => true,
'value' => date('Y-m-d', strtotime('18 years ago')),
],
'options' => [
'label' => 'Date of Birth',
'max_year' => date('Y', strtotime('18 years ago')),
],
]);
To render the form I am doing:
echo $this->form($form);
Anyway, the day element is being rendered in j format (i.e. day of the month without leading zeros 1 to 31).
How do I tell the element to render the day in d format (i.e. day of the month, 2 digits with leading zeros 01 to 31)?
I have check source code from Zend\Form\Element\DateSelect and it's view helper Zend\Form\View\Helper\FormDateSelect. The rendering date is on view helper, but it didn't use date('j'). It use IntlDateFormatter to format date, and it will output date format based on locale date format pattern given.
https://github.com/zendframework/zend-form/blob/release-2.2.0/src/View/Helper/FormDateSelect.php#L90
So, the solution we should pass the locale date format that use two digits day (dd). For country date format list, can be check here
https://en.wikipedia.org/wiki/Date_format_by_country
Based on the date format on list above, India use DD-MM-YY as date format. we can use this locale to get two digit day format,.
So, please use this on your view helper
echo $this->formDateSelect($form->get('date_of_birth'), IntlDateFormatter::MEDIUM, 'en_IN');
The view helper Zend\Form\View\Helper\FormDateSelect has a function getPattern that generates the patten by using the IntlDateFormatter class:
$intl = new IntlDateFormatter($this->getLocale(), $this->dateType, IntlDateFormatter::NONE);
$this->pattern = $intl->getPattern();
There did not appear to be any method of setting a pattern at element level, so I have extended this view helper allowing me to specify my own pattern:
<?php
namespace RPK\Form\View\Helper;
use Zend\Form\View\Helper\FormDateSelect as ZendFormDateSelect;
class FormDateSelect extends ZendFormDateSelect
{
/**
* Parse the pattern
*
* #param bool $renderDelimiters
* #return array
*/
protected function parsePattern($renderDelimiters = true)
{
//Replace `day` value of "d" with "dd"
$pattern = parent::parsePattern($renderDelimiters);
if($pattern['day'] === 'd') {
$pattern['day'] = 'dd';
}
return $pattern;
}
}
Very basically, this takes the returned pattern array (['day'=>'d', 'month' => 'MMMM', 'year' => 'yyyy']), checks if the value of day is a single letter "d" and, if so, replaces it with a double-d.
Someone who has made this change?
Today the BO product list show the end customer price excl and incl vat.
I want if possible to show our wholesale price and mour end customer price excl vat instead. This is probably a change in AdminProductController but I dont know how. I run PS 1.6.1.6
Regards
Anders Yuran
Open /controllers/admin/AdminProductsController.php from your PrestaShop root directory and in the __construct() function, you will see the following code:
$this->fields_list['price'] = array(
'title' => $this->l('Base price'),
'type' => 'price',
'align' => 'text-right',
'filter_key' => 'a!price'
);
This code is responsible for showing the price in products list, try replacing the code with the following:
$this->fields_list['price'] = array(
'title' => $this->l('WholeSale price'),
'type' => 'price',
'align' => 'text-right',
'filter_key' => 'a!wholesale_price'
);
Hope it helps.
We are having an issue where, in one of our Kendo charts we are developing to display some weekly data. The JSON that we're sending to the view looks like:
[
{"WeekofYear":45,"Value":96.08,"WeekBeginDate":"\/Date(1415422800000)\/"},
{"WeekofYear":46,"Value":97.40,"WeekBeginDate":"\/Date(1416027600000)\/"},
{"WeekofYear":47,"Value":96.50,"WeekBeginDate":"\/Date(1416632400000)\/"},
{"WeekofYear":48,"Value":93.93,"WeekBeginDate":"\/Date(1417237200000)\/"},
{"WeekofYear":49,"Value":96.76,"WeekBeginDate":"\/Date(1417842000000)\/"},
{"WeekofYear":50,"Value":94.50,"WeekBeginDate":"\/Date(1418446800000)\/"}
]
The dates in the JSON represent the date on each Saturday of the week in question. However, when we render the graph, it displays the date from the Sunday of the week instead, as displayed in the screenshot.
Chart Screenshot
We are using the following code in the Razor engine to generate the chart:
#(Html.Kendo().Chart<Dashboard.Models.CentralScheduling>()
.Name("CallsAnswered")
.Title("% of Calls Answered")
.Legend(legend => legend.Visible(false))
.DataSource(dataSource => dataSource
.Read(read => read.Action("CentralScheduling", "Dashboard").Data("filterStatusData")))
.Series(series =>
{
series.Line(d => d.Value)
.Tooltip(t => t.Visible(true).Template("#=value#%"));
})
.CategoryAxis(axis => axis
.Categories(model => model.WeekBeginDate) //WeekBeginDate holds the date at the end of the week for this particular chart
.Labels(labels => labels.Format("MM/dd/yyyy")
.Rotation(-60)
)
)
.ValueAxis(axis => axis
.Numeric().Labels(labels => labels.Format("{0}%"))
.Max(100)
)
.SeriesColors("#3aafff","#ffb800","#a7008f","#99c900","#FF0000", "#002060")
)
The filterStatusData function sets a flag that we use in the controller to generate the JSON for the calling chart.
I am at a loss to explain why a different date is being chosen for the chart rather than the one that we are supplying.
An option - this is comming from Telerik - is to pass the date as a string from the server instead of a .Net DateTime object. The client will parse it just like it does a date object. Use this format "yyyy-mm-dd HH:MM"
so your json would be something like:
[
{"WeekofYear":45,"Value":96.08,"WeekBeginDate":"2014-12-16 07:00"},
...
I have folowing schema:
Template
UserTemplate
template_id
Costs
template_id
amount
value
What I'm trying to do, is to create a sfWidgetFormDoctrineChoice that displays the shipping costs based on a UserTemplate id.
$this->widgetSchema['cost'] = new sfWidgetFormDoctrineChoice(array(
'model' => 'Costs',
'key_method' => 'getValue',
'method' => 'getAmount',
'add_empty' => 'Please Select Amount',
'expanded' => false,
'multiple' => false
));
This displays all of the Costs.
Ideally, I'd like it to limit it to the UserTemplate.
I have looked at creating a custom query and passing that into the widget, but I'm not sure if this would be the correct way of doing this
So If I have a bunch of costs assigned to the template id of 12 and the user template references 12, when I'm on example.com/user-template/12 - I'd expect to see the costs for this in my form widget.
Creating a custom query and passing it to the widget is exaclty what you're looking for. You will have to build the query depending on the template_id you use in the URL.
I'm trying to DRY up my code and I have two methods that do almost the same thing but add an extra fields for one instance. It is formatting JSON in Rails and trying to see if there is a way where I can perform an if statement within the result.collect similar to below. Any help is much appreciated
results.collect{ |result| { :type => defined?(result.type) ? result.type : "Total",
:jan => result.jan, :feb => result.feb, :mar => result.mar, :apr => result.apr,
:may => result.may, :jun => result.jun, :jul => result.jul, :aug => result.aug,
:sep => result.sep, :oct => result.oct, :nov => result.nov, :dec => result.dec } }
in this statement
:type => defined?(result.type) ? result.type : "Total"
I want to be able perform a check if result.type exists in the query then list it else just put "Total"
Any ideas how to perform this? Thanks everyone
I ended up writing in the method to check if with_type or not. If true then I added the type select statement in and if false then added
Select 'Total' as Type
I was hoping to figure out how to modify the json as in the question but modifying the composed_scope worked too.