I'm using Eleventy and using Posts. I have set the date in the meta data using the format
date: 2021-09-10.
I can display the full date using
{{ page.date | readableDate }}
But I want to display just the year (YYYY) within the post content. I'm using Nunjucks.
How do i do this?
I've tried
{{ page.date.getFullYear }}
This gives the following error:
function () { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return obj[val].apply(obj, args); }
Any help would be really appreciated - thanks!
Add a filter to your .eleventy.js file
eleventyConfig.addFilter("justYear", (dateString) => {
dateObj = new Date(dateString);
return DateTime.fromJSDate(dateObj, { zone: 'utc' }).toFormat('yyyy');
});
Then in your .njk file
{{ page.date | justYear }}
Related
Using a Syncfusion EJS Autocomplete element in a search box.
The issue being reported is that the user is not able to select the value searched
I know the issue, is because the data passed to the AutoComplete has some duplicate values, but they are distinct based on a second value.
The code below hopefully show the issue
<div class="control-section" style="margin:130px auto;width:300px">
<ejs-autocomplete
id="sample-list"
#sample
[dataSource]="countriesData"
[autofill]="isBool"
[fields]="fields"
(select)='selectIssuer($event)'
filterType="Contains"
>
<ng-template #itemTemplate let-data>
<!--set the value to itemTemplate property-->
<div class='item'>
<div>{{data.Name}} -- {{data.Structure != 'SPV' ? 'BT' : data.Structure}}</div>
</div>
</ng-template>
</ejs-autocomplete>
</div>
/**
* AutoComplete Highlight Sample
*/
import { Component, ViewChild } from '#angular/core';
import { AutoCompleteComponent } from '#syncfusion/ej2-angular-dropdowns';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css'],
})
export class AppComponent {
public countriesData = [
{ Name: 'Client 1' , Id: 'A3D49279-18DC-40FB-B843-B6207518B379', Structure: 'BT'},
{ Name: 'Client 1' , Id: '77ED2BD8-2309-4792-9264-01DEAFC3227E', Structure: 'SPV'},
{ Name: 'Client 2' , Id: 'BA017D4F-DD5C-4F2D-852C-DD17AF209436', Structure: 'BT'},
{ Name: 'Client 3' , Id: '78FCDCB9-06EA-4D9B-A352-171B1594AE24', Structure: 'SPV'},
{ Name: 'Client 4' , Id: '48C3168A-FA2A-4EF7-B184-61F18C47AB6D', Structure: 'BT'},
{ Name: 'Client 4' , Id: 'E734CA83-91FF-4475-B35E-BE232ACBF137', Structure: 'SPV'}
];
public fields: Object = { value: 'Name' };
public isBool: Boolean = true;
}
selectIssuer(_issuer: any) {
this.getSearchIssuer.emit({ issuer: <CombinedIssuer>_issuer.itemData, clear: false });
}
AS is visible, some of the Client Names are the same, but what makes them distinct is the combination with the Structure.
The issue is that when a user selects say Client 4 that has an SPV Structure, it still loads the Client 4 with the BT structure.
Is it possible for the EJS Autocomplete to take in to consideration the combination of fields to make sure the correct item is selected or is is possible for the EJS Autocomplte to use the Item Id as well
Can it be possible to pass in the Id value to the Fields property ?
I was able to figure this out, so sharing my findings:
The additional code is shown below with ...
<ejs-autocomplete id='combinedIssuerSearch' #searchCombinedIssuers
[dataSource]='ixDispalyCombinedIssuerList'
[fields]='issuerFields'
ShowBorder='False'
(select)='selectIssuer($event)'
[placeholder]='defaultText'
[filterType]='issuerFilterType'
*(filtering)='onFiltering($event)'*
[showClearButton]="false"
class="auto-complete-search">
<ng-template #itemTemplate let-data>
<!--set the value to itemTemplate property-->
<div class='item'>
<div class='issuer-name'> {{data.Name}}</div>
<div class="ls_spv">{{data.Structure != 'SPV' ? 'BT' : data.Structure}}</div>
</div>
</ng-template>
</ejs-autocomplete>
in the ts file I added code to handle the OnFiltering event
onFiltering(args) {
args.preventDefaultAction = true;
var predicate = new Predicate('Name', 'contains', args.text, true);
predicate = predicate.or('Structure', 'contains', args.text, true);
var query = new Query();
query = args.text != '' ? query.where(predicate) : query;
args.updateData(this.ixDispalyCombinedIssuerList, query);
}
I use mapbox tools for my autofill place address autocomplete on my project Symfony
I want to know how can i extract full complete address in autofill, i have 2 inputs one for search and one hidden for get full/complete address
<mapbox-address-autofill>
{{ form_widget( form.address, {
'attr': {
'class': 'form-control form-control-solid font-weight-bold',
'placeholder': 'Adresse de départ',
'required': 'required',
'autocomplete': 'address-line1'
}
} ) }}
{{ form_widget( form.address_value, {
'attr': {
'autocomplete': 'full-address'
}
}) }}
</mapbox-address-autofill>
I have this but with tag 'full-addresse' 'complete' 'place_name'
No one workn if you have any solution for get full address to persist this in php Symfony project
"full_address" is a property of the feature object that is returned from a retrieve event, but does not automatically map to any HTML form field autocomplete value. The only object properties that get mapped to HTML elements are the ones corresponding to WHATWG standards, i.e.:
'street-address'
'address-line1'
'address-line2'
'address-line3'
'address-level1'
'address-level2'
'address-level3'
'address-level4'
'country'
'country-name'
'postal-code'
I'm not familiar with PHP, but a way to do this in Javascript would be something like:
const autofill = document.querySelector('mapbox-address-autofill');
const targetInput = document.getElementById('myTargetInput');
autofill.addEventListener('retrieve', (event) => {
const featureCollection = event.detail;
const feature = featureCollection[0];
const fullAddress = feature.properties.full_address;
targetInput.value = fullAddress;
});
I have an array of calendar events with a pre-formatted date: 20190517T010000Z.
I need to filter the array based upon the following:
1) Future Events (any events occurring greater than NOW)
2) Past Events (any events that occurred less than NOW)
3) New Events created within the past 7 days (NOW - 7 days)
I have an example hardcoded below - but need NOW to be dynamic and based upon the user's system time. I can't figure out how to get NOW in the same format as the datetime format I'm getting in the my array. Also, I don't know where in my code it should reside (within a separate JS file or within the Vue component)?
Once I have it working within the component listed below, it will be moved to a VUEX Getter.
<template>
<div class="text-left m-4 p-4">
<div>
Total Number Events: {{ allEvents.length }}
</div>
<div>
Events Created In Last 7 Days: {{ createdEvents }}
</div>
<div>
Future Events: {{ futureEvents }}
</div>
<div>
Past Events: {{ pastEvents }}
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['allEvents']),
futureEvents () {
return this.$store.state.allEvents.filter(allEvents => allEvents.dtstart >= '20190517T010000Z').length
},
pastEvents () {
return this.$store.state.allEvents.filter(allEvents => allEvents.dtstart <= '20190517T235900Z').length
},
createdEvents () {
return this.$store.state.allEvents.filter(
allEvents => allEvents.created >= '20190511T235900Z' && allEvents.created <= '20190517T235900Z' )
.length
}
},
}
</script>
The above code works - but it is hardcoded right now and it needs to be dynamic. Any thoughts or suggestions would be welcome.
All your date time objects should be persisted as UNIX timestamps (UTC seconds since 1/1/1970). This will allow you to compare times across systems no matter the timezone.
Provided that the events in your Vuex store are stored with dstart being a UNIX timestamp, the following snippet should give you the dynamic behaviour you want.
I've created a now attribute in the component's data. This gets updated every second, causing the computed properties to refresh.
Additionally, if the allEvents property in the Vuex store updates, the computed properties will also refresh.
<template>
<div class="text-left m-4 p-4">
<div>
Total Number Events: {{ allEvents.length }}
</div>
<div>
Events Created In Last 7 Days: {{ createdEvents }}
</div>
<div>
Future Events: {{ futureEvents }}
</div>
<div>
Past Events: {{ pastEvents }}
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
data () {
return {
now: new Date().getUTCSeconds()
}
},
created () {
this.scheduleUpdateNow();
},
methods: {
updateNow() {
this.now = new Date().getUTCSeconds();
this.scheduleUpdateNow();
},
scheduleUpdateNow() {
setTimeout(this.updateNow, 1000);
}
},
computed: {
...mapState(['allEvents']),
futureEvents () {
return this.$store.state.allEvents.filter(allEvents => allEvents.dtstart > this.now).length
},
pastEvents () {
return this.$store.state.allEvents.filter(allEvents => allEvents.dtstart <= this.now).length
},
createdEvents () {
return this.$store.state.allEvents.filter(
allEvents => allEvents.created >= this.now && allEvents.created <= this.now).length
}
}
}
</script>
I am working on i18n for angular and I would like to provide a translation for form errors. But I do not know how to do that. I followed the guide from angular website. And I tried to use the select method but it is not working.
Initially, before trying to translate, I had the following code in my component.ts:
onValueChanged(data?: any) {
if (!this.userForm) { return; }
const form = this.userForm;
for (const field in this.formErrors) {
// clear previous error message (if any)
this.formErrors[field] = '';
const control = form.get(field);
if (control && control.dirty && !control.valid) {
const messages = this.validationMessages[field];
for (const key in control.errors) {
this.formErrors[field] += messages[key] + ' ';
}
}
}
}
formErrors = {
'firstname': ''
};
validationMessages = {
'firstname': {
'required': 'Firstname is required.',
'pattern': 'Only alphabetics caracters are allowed.'
}
};
And the following code in my component.html:
<div *ngIf="formErrors.firstname" class="form-control-feedback alert">
{{ formErrors.firstname }}
</div>
It worked perfectly because there was no translation. Then, I made the following updates:
In the component.ts:
validationMessages = {
'firstname': {
'required': 'required',
'pattern': 'pattern'
}
};
In the component.html:
<div *ngIf="formErrors.firstname" class="form-control-feedback alert">
<ng-container i18n="##userModalFirstnameError">
{formErrors.firstname, select, required {required} pattern {pattern}}
</ng-container>
</div>
In the messages.fr.xlf file, I have this:
<trans-unit id="userModalFirstnameError" datatype="html">
<source>{VAR_SELECT, select, required {required} pattern {pattern} }</source>
<target>
{VAR_SELECT, select, required {Nom utilisateur obligatoire} pattern {pattern}}
</target>
...
</trans-unit>
Unfortunately, this solution does not work.
I finally found where the issue comes from. Actually, there were 2 mistakes.
The first one is related to the 'VAR_SELECT' in the .xlf file. It has been generated by Angular with the build command => "ng-xi18n --i18nFormat=xlf". This 'VAR_SELECT' works well if a "direct" variable is used (for example if I put "{toto, select, required {required} pattern {pattern}}" and toto was equal to "required"). But it seems that it does not work if a variable from table is used (which is my case with the variable "formErrors.firstname"). So I replaced 'VAR_SELECT' in the .xlf file by the name of my variable 'formErrors.firstname'.
The second one is in the "onValueChanged" function:
for (const key in control.errors) {
this.formErrors[field] += messages[key] + ' ';
}
Because of the space character at the end, the variable did not match one of the values defined (for example, it was 'required ' where I was expected 'required'. Note the additional space at the end of the 1st value)
On my Symfony2 project I got a list of arguments :
<ul class="arguments" data-prototype="{{ form_widget(form.arguments.vars.prototype)|e('html_attr') }}">
{% for argument in form.arguments %}
{#<li>{{ form_row(argument) }}</li>#}
<li>
{{ form_row(argument.name, {'label': 'Name'}) }}
{{ form_row(argument.french_description) }}
{{ form_row(argument.english_description) }}
{{ form_row(argument.return) }}
{{ form_row(argument.type) }}
</li>
{% endfor %}
</ul>
But I got a button "Add arguments", creating a new < li >< /li > with arguments fields. The problem is the new argument don't got the custom label "Name".
EDIT :
I add the arguments with a buton calling a JS function to add my fields on the page. Then when I click on submit it save it to database.
$('#add_argument_link').on('click', function(e) {
// prevent the link from creating a "#" on the URL
e.preventDefault();
// setup an "add a argument" link
var $newLinkLi = $('<li></li>');
// add a new argument form (see next code block)
addArgumentForm($collectionHolder, $newLinkLi);
addTagFormDeleteLink($newLinkLi);
});
Thanks for your help.
You can try something like that :
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var $container = $('div#name_of_your_div');
var index = $container.find(':input').length;
$('#add_argument').click(function(e) {
addArgument($container);
e.preventDefault();
return false;
});
if (index == 0) {
addArgument($container);
} else {
$container.children('div').each(function() {
addDeleteLink($(this));
});
}
function addArgument($container) {
var template = $container.attr('data-prototype')
.replace(/__name__label__/g, 'Argument number' + (index+1))
.replace(/__name__/g, index);
var $prototype = $(template);
addDeleteLink($prototype);
$container.append($prototype);
index++;
}
function addDeleteLink($prototype) {
var $deleteLink = $('Delete');
$prototype.append($deleteLink);
$deleteLink.click(function(e) {
$prototype.remove();
e.preventDefault();
return false;
});
}
});
</script>