I have two BootstrapVue datepickers in my form in Vue.js. I'd like to implement a holiday manager, so you can define the start (input-3) and end date (input-4) of your holiday. The end date should be greater or equal to the start date. My current implementation looks as follows:
<b-form-group
id="input-group-3"
label="Anfangsdatum:"
label-for="input-3"
>
<b-form-datepicker
id="input-3"
v-model="von"
placeholder="Anfangsdatum auswählen"
required
:min="minAnfang"
></b-form-datepicker>
</b-form-group>
<b-form-group id="input-group-4" label="Enddatum:" label-for="input-4">
<b-form-datepicker
id="input-4"
v-model="bis"
placeholder="Enddatum auswählen"
:min="minEnde"
required
></b-form-datepicker>
</b-form-group>
The data part in Vue is implemented as follows:
data() {
const datum = new Date();
const datum_heute = new Date(datum.getFullYear(), datum.getMonth(), datum.getDate());
const minVon = new Date(datum_heute);
minVon.setDate(minVon.getDate()+ 1);
const minBis = new Date(datum_heute);
minBis.setDate(minVon.getDate()+1);
return {
Urlaubsart: "",
Grund: "",
von: "",
bis: "",
Status: "",
BenutzerID: 24,
minAnfang: minVon,
minEnde: minBis,
arten: [
{ value: null, text: "Wählen Sie die Urlaubsart aus" },
{ value: "Urlaub", text: "Urlaub" },
{ value: "Sonderurlaub", text: "Sonderurlaub" },
],
gruende: [
{ value: "Umzug", text: "Umzug" },
{ value: "Hochzeit", text: "Hochzeit" },
{ value: "Geburt", text: "Geburt" },
{ value: "Umzug", text: "Sonstiges" },
],
Urlaubstage: "",
};
}
So how can I ensure, that the end date is equal to the start date or greater?
I've created a codepen for you: https://codepen.io/mtveerman/pen/gOwwNoL
(note that I use vuetify as the layout engine, but you'll get the idea)
What I did:
Define an internalBis property
Define a computed bis property with a get and set function:
Set the internalBis property in the set function
Compare von and internalBis in the get function, return von if internalBis is smaller than von
In your components and form submissions you should only work with bis, since that will always return the correct value. Note that if von now changes to a date after the original bis, bis is automatically changing as well.
For you, the most interesting code is this:
data: () => ({
von: new Date().toISOString().substr(0, 10),
internalBis: new Date().toISOString().substr(0, 10)
}),
computed: {
bis: {
// getter
get: function () {
if (this.internalBis < this.von) {
return this.von
}
return this.internalBis
},
// setter
set: function (newValue) {
this.internalBis = newValue
}
}
}
Hi everyone i need your help.
I put dates in Jquery in my form with the id:
twig :
{{ form_label(Form.date, 'Date') }}
{{ form_widget(Form.date, {'id': 'datejquery', 'attr': {'class' :'form-control'}}) }}
formType :
$builder->add('date', DateType::class, ['label' => 'Date', 'widget' => 'single_text', 'html5' => false, 'format' => 'dd/MM/yyyy']);
The code works with 'format' => 'dd/MM/yyyy'
But the display of the datepicker no longer works when I click on the form fields.
I just have the date that appears in the input but I don't have the calendar display...
When : {'class' :'js-datepicker'}})
display empty calendar
In my project the data is coming to front-end as a json object as shown below:
{
id: 1,
meetingName: "Meeting 1",
meetingDate: "2018-02-21",
startTime: "10:00:00"
}
<td>{{meeting.startTime|date:"h:mma"}}</td>
I used the above method to format the date in angularjs code as 10:00 AM.
But the start time is still shown as 10:00:00. Why is it not formatting the date according to the format?
date filter expects a date object as input. But you are passing a string. Below is a sample code that show the date as expected.
var app = angular.module('myApp', []);
app.controller('datCtrl', function($scope) {
let info = {
id: 1,
meetingName: "Meeting 1",
meetingDate: "2018-02-21",
startTime: "10:00:00"
}
$scope.meetingDate= new Date(info.meetingDate + " " + info.startTime);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="datCtrl">
<p>Meeting Time= {{ meetingDate | date:"h:mma" }}</p>
</div>
</body>
Date Filter Docs
Hope this helps :)
Filter date expects an object of type date. This custom filter could help you:
View
<div ng-controller="MyCtrl">
{{data.startTime|timeFilter: data.meetingDate: 'h:mma'}}
{{data.startTime|timeFilter: data.meetingDate: 'yyyy-MM-dd HH:mm:ss Z'}}
</div>
AngularJS application
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.data = {
id: 1,
meetingName: "Meeting 1",
meetingDate: "2018-02-21",
startTime: "10:00:00"
};
});
myApp.filter('timeFilter', function ($filter) {
return function (data, aDate, dateFilter) {
return $filter('date')(new Date(aDate + " " + data), dateFilter);
}
})
> Demo fiddle
I'm developing a small app with CakePHP and I need to save a startdate and an enddate for an event. I went with the Bootstrap Daterangepicker to let users visually input the dates.
In my add.ctp view I have two fields:
<div class="form-group">
<?php echo $this->Form->input('start', array(
'class' => 'form-control',
'type' => 'text',
'id' => 'start',
'name' => 'start',
'data-mask')); ?>
</div><!-- .form-group -->
<div class="form-group">
<?php echo $this->Form->input('end', array(
'class' => 'form-control',
'type' => 'text',
'id' => 'end',
'name' => 'end',
'data-mask')); ?>
</div>
And the Javascript that controls the inputs:
<script type="text/javascript">
$(function() {
$('input[name="start"]').daterangepicker({
timePicker24Hour: true,
singleDatePicker: true,
timePicker: false,
timePickerIncrement: 30,
locale: {
format: 'YYYY-MM-DD HH:mm:ss'
}
});
$('input[name="end"]').daterangepicker({
timePicker24Hour: true,
singleDatePicker: true,
timePicker: false,
timePickerIncrement: 30,
locale: {
format: 'YYYY-MM-DD HH:mm:ss'
}
});
});
</script>
The picker works just fine, it updates the field values properly, but when I attempt to save the form, the start field gets written to the database as follows:
start 0000-00-00 00:00:00
end (null)
The form data for the start and end fields saves properly if I'm reverting to the default configuration of the fields.
Any clue as to where I'm failing would be highly appreciated.
try something like this
$correctdate = date("Y-m-d j:h:m",strtotime($yourdate));
It's not a great peace of code, but it should help to go further in the right direction.
We take this string and make a timestamp out of it. Then we change it to a proper datetime value.
Okay, so I was passing text to a datetime field and the save operation failed. In order to fix this I had to convert the strings to the proper type by processing it in the beforeSave() function of the model.
Here is the code that worked for me:
public function beforeSave($options = array()) {
if (!empty($this->data['Task']['start']) && !empty($this->data['Task']['end'])) {
$this->data['Task']['start'] = $this->dateFormatBeforeSave($this->data['Task']['start']);
$this->data['Task']['end'] = $this->dateFormatBeforeSave($this->data['Task']['end']);
}
return true;
}
public function dateFormatBeforeSave($dateString) {
return date('Y-m-d h:m:s', strtotime($dateString));
}
My goal is to apply a formatting filter that is set as a property of the looped object.
Taking this array of objects:
[
{
"value": "test value with null formatter",
"formatter": null,
},
{
"value": "uppercase text",
"formatter": "uppercase",
},
{
"value": "2014-01-01",
"formatter": "date",
}
]
The template code i'm trying to write is this:
<div ng-repeat="row in list">
{{ row.value | row.formatter }}
</div>
And i'm expecting to see this result:
test value with null formatter
UPPERCASE TEXT
Jan 1, 2014
But maybe obviusly this code throws an error:
Unknown provider: row.formatterFilterProvider <- row.formatterFilter
I can't immagine how to parse the "formatter" parameter inside the {{ }}; can anyone help me?
See the plunkr http://plnkr.co/edit/YnCR123dRQRqm3owQLcs?p=preview
The | is an angular construct that finds a defined filter with that name and applies it to the value on the left. What I think you need to do is create a filter that takes a filter name as an argument, then calls the appropriate filter (fiddle) (adapted from M59's code):
HTML:
<div ng-repeat="row in list">
{{ row.value | picker:row.formatter }}
</div>
Javascript:
app.filter('picker', function($filter) {
return function(value, filterName) {
return $filter(filterName)(value);
};
});
Thanks to #karlgold's comment, here's a version that supports arguments. The first example uses the add filter directly to add numbers to an existing number and the second uses the useFilter filter to select the add filter by string and pass arguments to it (fiddle):
HTML:
<p>2 + 3 + 5 = {{ 2 | add:3:5 }}</p>
<p>7 + 9 + 11 = {{ 7 | useFilter:'add':9:11 }}</p>
Javascript:
app.filter('useFilter', function($filter) {
return function() {
var filterName = [].splice.call(arguments, 1, 1)[0];
return $filter(filterName).apply(null, arguments);
};
});
I like the concept behind these answers, but don't think they provide the most flexible possible solution.
What I really wanted to do and I'm sure some readers will feel the same, is to be able to dynamically pass a filter expression, which would then evaluate and return the appropriate result.
So a single custom filter would be able to process all of the following:
{{ammount | picker:'currency:"$":0'}}
{{date | picker:'date:"yyyy-MM-dd HH:mm:ss Z"'}}
{{name | picker:'salutation:"Hello"'}} //Apply another custom filter
I came up with the following piece of code, which utilizes the $interpolate service into my custom filter. See the jsfiddle:
Javascript
myApp.filter('picker', function($interpolate ){
return function(item,name){
var result = $interpolate('{{value | ' + arguments[1] + '}}');
return result({value:arguments[0]});
};
});
One way to make it work is to use a function for the binding and do the filtering within that function. This may not be the best approach: Live demo (click).
<div ng-repeat="row in list">
{{ foo(row.value, row.filter) }}
</div>
JavaScript:
$scope.list = [
{"value": "uppercase text", "filter": "uppercase"}
];
$scope.foo = function(value, filter) {
return $filter(filter)(value);
};
I had a slightly different need and so modified the above answer a bit (the $interpolate solution hits the same goal but is still limited):
angular.module("myApp").filter("meta", function($filter)
{
return function()
{
var filterName = [].splice.call(arguments, 1, 1)[0] || "filter";
var filter = filterName.split(":");
if (filter.length > 1)
{
filterName = filter[0];
for (var i = 1, k = filter.length; i < k; i++)
{
[].push.call(arguments, filter[i]);
}
}
return $filter(filterName).apply(null, arguments);
};
});
Usage:
<td ng-repeat="column in columns">{{ column.fakeData | meta:column.filter }}</td>
Data:
{
label:"Column head",
description:"The label used for a column",
filter:"percentage:2:true",
fakeData:-4.769796600014472
}
(percentage is a custom filter that builds off number)
Credit in this post to Jason Goemaat.
Here is how I used it.
$scope.table.columns = [{ name: "June 1 2015", filter: "date" },
{ name: "Name", filter: null },
] etc...
<td class="table-row" ng-repeat="column in table.columns">
{{ column.name | applyFilter:column.filter }}
</td>
app.filter('applyFilter', [ '$filter', function( $filter ) {
return function ( value, filterName ) {
if( !filterName ){ return value; } // In case no filter, as in NULL.
return $filter( filterName )( value );
};
}]);
I improved #Jason Goemaat's answer a bit by adding a check if the filter exists, and if not return the first argument by default:
.filter('useFilter', function ($filter, $injector) {
return function () {
var filterName = [].splice.call(arguments, 1, 1)[0];
return $injector.has(filterName + 'Filter') ? $filter(filterName).apply(null, arguments) : arguments[0];
};
});
The newer version of ng-table allows for dynamic table creation (ng-dynamic-table) based on a column configuration. Formatting a date field is as easy as adding the format to your field value in your columns array.
Given
{
"name": "Test code",
"dateInfo": {
"createDate": 1453480399313
"updateDate": 1453480399313
}
}
columns = [
{field: 'object.name', title: 'Name', sortable: 'name', filter: {name: 'text'}, show: true},
{field: "object.dateInfo.createDate | date :'MMM dd yyyy - HH:mm:ss a'", title: 'Create Date', sortable: 'object.dateInfo.createDate', show: true}
]
<table ng-table-dynamic="controller.ngTableObject with controller.columns" show-filter="true" class="table table-condensed table-bordered table-striped">
<tr ng-repeat="row in $data">
<td ng-repeat="column in $columns">{{ $eval(column.field, { object: row }) }}</td>
</tr>
</table>
I ended up doing something a bit more crude, but less involving:
HTML:
Use the ternary operator to check if there is a filter defined for the row:
ng-bind="::data {{row.filter ? '|' + row.filter : ''}}"
JS:
In the data array in Javascript add the filter:
, {
data: 10,
rowName: "Price",
months: [],
tooltip: "Price in DKK",
filter: "currency:undefined:0"
}, {
This is what I use (Angular Version 1.3.0-beta.8 accidental-haiku).
This filter allows you to use filters with or without filter options.
applyFilter will check if the filter exists in Angular, if the filter does not exist, then an error message with the filter name will be in the browser console like so...
The following filter does not exist: greenBananas
When using ng-repeat, some of the values will be undefined. applyFilter will handle these issues with a soft fail.
app.filter( 'applyFilter', ['$filter', '$injector', function($filter, $injector){
var filterError = "The following filter does not exist: ";
return function(value, filterName, options){
if(noFilterProvided(filterName)){ return value; }
if(filterDoesNotExistInAngular(filterName)){ console.error(filterError + "\"" + filterName + "\""); return value; }
return $filter(filterName)(value, applyOptions(options));
};
function noFilterProvided(filterName){
return !filterName || typeof filterName !== "string" || !filterName.trim();
}
function filterDoesNotExistInAngular(filterName){
return !$injector.has(filterName + "Filter");
}
function applyOptions(options){
if(!options){ return undefined; }
return options;
}
}]);
Then you use what ever filter you want, which may or may not have options.
// Where, item => { name: "Jello", filter: {name: "capitalize", options: null }};
<div ng-repeat="item in items">
{{ item.name | applyFilter:item.filter.name:item.filter.options }}
</div>
Or you could use with separate data structures when building a table.
// Where row => { color: "blue" };
// column => { name: "color", filter: { name: "capitalize", options: "whatever filter accepts"}};
<tr ng-repeat="row in rows">
<td ng-repeat="column in columns">
{{ row[column.name] | applyFilter:column.filter.name:column.filter.options }}
</td>
</tr>
If you find that you require to pass in more specific values you can add more arguments like this...
// In applyFilter, replace this line
return function(value, filterName, options){
// with this line
return function(value, filterName, options, newData){
// and also replace this line
return $filter(filterName)(value, applyOptions(options));
// with this line
return $filter(filterName)(value, applyOptions(options), newData);
Then in your HTML perhaps your filter also requires a key from the row object
// Where row => { color: "blue", addThisToo: "My Favorite Color" };
// column => { name: "color", filter: { name: "capitalize", options: "whatever filter accepts"}};
<tr ng-repeat="row in rows">
<td ng-repeat="column in columns">
{{ row[column.name] | applyFilter:column.filter.name:column.filter.options:row.addThisToo }}
</td>
</tr>