Continuing from Evan’s blog post on building pages with Paragraphs and writing custom blocks of content as fields, I will walk you through how to create a custom field-formatter in Drupal 8 by example.
A field-formatter is the last piece of code to go with the field-type and the field-widget that Evan wrote about in the previous blog post. While the field-type tells Drupal about what data comprises a field, the field-formatter is responsible for telling Drupal how to display the data stored in the field.
To recap, we defined a hashtag_search
field type in the previous blog post whose instances will be composed of two items: the hashtag to search for, and the number of items to display. We want to convert this data into a list of the most recent n tweets with the specified hashtag.
A field-formatter is a Drupal plugin, just like its respective field-type and field-widget. They live in <module_path>/src/Plugin/Field/FieldFormatter/
and are namespaced appropriately: Drupal\<module_name>\Plugin\Field\FieldFormatter
.
<?php
namespace Drupal\my_module\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
/**
* @FieldFormatter(
* id = "hashtag_formatter",
* label = @Translation("Hashtag Search"),
* field_types = {
* "hashtag_search"
* }
* )
*/
class HashtagFormatter extends FormatterBase
{
public function viewElements(FieldItemListInterface $items, $langcode)
{
return array();
}
}
We tell Drupal important details about our new field-formatter using a @FieldFormatter
class annotation. We declare its unique id
; a human-readable, translatable label
; and a list of field_types
that it supports.
The most important method in a field-formatter is the viewElements
method. It’s responsibility is returning a render array based on field data being passed as <Drupal\Core\Field\FieldItemListInterface> $items
.
Let’s look at the code:
<?php
use Drupal\my_module\Twitter\TwitterClient;
use Drupal\my_module\Twitter\TweetFormatter;
...
/**
* @var TwitterClient
*/
protected $twitter;
/**
* @var TweetFormatter
*/
protected $formatter;
...
public function viewElements(FieldItemListInterface $items, $langcode)
{
$element = [];
// Iterate through all values from one ore more fields...
foreach ($items as $delta => $item) {
try {
// Use service to fetch `$item->count` no. of tweets matching the hashtag...
$results = $this->twitter->search($item->hashtag_search, $item->count);
// Map through each tweet and generate an HTML-rich version
// complete with hashtags, mentions, URLs, etc. as links, using a formatter service.
// Assign the HTML-rich version to a "formatted_text" property.
$statuses = array_map(function ($s) {
$s['formatted_text'] = $this->formatter->toHtml($s['text'], $s['entities']);
return $s;
}, $results['statuses']);
// Add a header...
if (!empty($statuses)) {
$element[$delta]['header'] = [
'#markup' => '<h4>#' . $item->hashtag_search . '</h4>'
];
}
// Tell Drupal that each status is to be rendered
// by the `my_module_status` theme.
foreach ($statuses as $status) {
$element[$delta]['status'][] = [
'#theme' => 'my_module_status',
'#status' => $status
];
}
} catch (\Exception $e) {
// If an error/exception occur i.e. Twitter auth errors, log it, and carry-on
// gracefully...
$this->logger->error('[:exception]: %message', [
':exception' => get_class($e),
'%message' => $e->getMessage(),
]);
continue;
}
}
// Include the `twitter_intents` library defined by this module which holds
// `Drupal.behavior`s that dictate functionality of the Twitter block UI.
$element['#attached']['library'][] = 'my_module/twitter_intents';
return $element;
}
...
See https://github.com/bezhermoso/tweet-to-html-php for how
TweetFormatter
works. Also, you can find the source-code for the basic Twitter HTTP client here: https://gist.github.com/bezhermoso/5a04e03cedbc77f6662c03d774f784c5Custom theme renderer
As shown above, each individual tweets are using the
my_module_status
render theme. We’ll define it in themy_module.module
file:<?php /** * Implements hook_theme(). */ function my_module_theme($existing, $type, $theme, $path) { $theme = []; $theme['my_module_status'] = array( 'variables' => array( 'status' => NULL ), 'template' => 'twitter-status', 'render element' => 'element', 'path' => $path . '/templates' ); return $theme; }
With this, we are telling Drupal to use the template file
modules/my_module/templates/twitter-status.twig.html
for any render array usingmy_module_status
as its theme.
Read More 4001
Read More 4002
Read More 4003
Read More 4004
Read More 4005
Read More 4006
Read More 4007
Read More 4008
Read More 4009
Read More 4010
Read More 4011
Read More 4012
Read More 4013
Read More 4014
Read More 4015
Read More 4016
Read More 4017
Read More 4018
Read More 4019
Read More 4020
Read More 4021
Read More 4022
Read More 4023
Read More 4024
Read More 4025
Read More 4026
Read More 4027
Read More 4028
Read More 4029
Read More 4030
Read More 4031
Read More 4032
Read More 4033
Read More 4034
Read More 4035
Read More 4036
Read More 4037
Read More 4038
Read More 4039
Read More 4040
Read More 4041
Read More 4042
Read More 4043
Read More 4044
Read More 4045
Read More 4046
Read More 4047
Read More 4048
Read More 4049
Read More 4050
Read More 4051
Read More 4052
Read More 4053
Read More 4054
Read More 4055
Read More 4056
Read More 4057
Read More 4058
Read More 4059
Read More 4060
Read More 4061
Read More 4062
Read More 4063
Read More 4064
Read More 4065
Read More 4066
Read More 4067
Read More 4068
Read More 4069
Read More 4070
Read More 4071
Read More 4072
Read More 4073
Read More 4074
Read More 4075
Read More 4076
Read More 4077
Read More 4078
Read More 4079
Read More 4080
Read More 4081
Read More 4082
Read More 4083
Read More 4084
Read More 4085
Read More 4086
Read More 4087
Read More 4088
Read More 4089
Read More 4090
Read More 4091
Read More 4092
Read More 4093
Read More 4094
Read More 4095
Read More 4096
Read More 4097
Read More 4098
Read More 4099
Read More 4100
Read More 4101
Read More 4102
Read More 4103
Read More 4104
Read More 4105
Read More 4106
Read More 4107
Read More 4108
Read More 4109
Read More 4110
Read More 4111
Read More 4112
Read More 4113
Read More 4114
Read More 4115
Read More 4116
Read More 4117
Read More 4118
Read More 4119
Read More 4120
Read More 4121
Read More 4122
Read More 4123
Read More 4124
Read More 4125
Read More 4126
Read More 4127
Read More 4128
Read More 4129
Read More 4130
Read More 4131
Read More 4132
Read More 4133
Read More 4134
Read More 4135
Read More 4136
Read More 4137
Read More 4138
Read More 4139
Read More 4140
Read More 4141
Read More 4142
Read More 4143
Read More 4144
Read More 4145
Read More 4146
Read More 4147
Read More 4148
Read More 4149
Read More 4150
Read More 4151
Read More 4152
Read More 4153
Read More 4154
Read More 4155
Read More 4156
Read More 4157
Read More 4158
Read More 4159
Read More 4160
Read More 4161
Read More 4162
Read More 4163
Read More 4164
Read More 4165
Read More 4166
Read More 4167
Read More 4168
Read More 4169
Read More 4170
Read More 4171
Read More 4172
Read More 4173
Read More 4174
Read More 4175
Read More 4176
Read More 4177
Read More 4178
Read More 4179
Read More 4180
Read More 4181
Read More 4182
Read More 4183
Read More 4184
Read More 4185
Read More 4186
Read More 4187
Read More 4188
Read More 4189
Read More 4190
Read More 4191
Read More 4192
Read More 4193
Read More 4194
Read More 4195
Read More 4196
Read More 4197
Read More 4198
Read More 4199
Read More 4200
Read More 4201
Read More 4202
Read More 4203
Read More 4204
Read More 4205
Read More 4206
Read More 4207
Read More 4208
Read More 4209
Read More 4210
Read More 4211
Read More 4212
Read More 4213
Read More 4214
Read More 4215
Read More 4216
Read More 4217
Read More 4218
Read More 4219
Read More 4220
Read More 4221
Read More 4222
Read More 4223
Read More 4224
Read More 4225
Read More 4226
Read More 4227
Read More 4228
Read More 4229
Read More 4230
Read More 4231
Read More 4232
Read More 4233
Read More 4234
Read More 4235
Read More 4236
Read More 4237
Read More 4238
Read More 4239
Read More 4240
Read More 4241
Read More 4242
Read More 4243
Read More 4244
Read More 4245
Read More 4246
Read More 4247
Read More 4248
Read More 4249
Read More 4250
Read More 4251
Read More 4252
Read More 4253
Read More 4254
Read More 4255
Read More 4256
Read More 4257
Read More 4258
Read More 4259
Read More 4260
Read More 4261
Read More 4262
Read More 4263
Read More 4264
Read More 4265
Read More 4266
Read More 4267
Read More 4268
Read More 4269
Read More 4270
Read More 4271
Read More 4272
Read More 4273
Read More 4274
Read More 4275
Read More 4276
Read More 4277
Read More 4278
Read More 4279
Read More 4280
Read More 4281
Read More 4282
Read More 4283
Read More 4284
Read More 4285
Read More 4286
Read More 4287
Read More 4288
Read More 4289
Read More 4290
Read More 4291
Read More 4292
Read More 4293
Read More 4294
Read More 4295
Read More 4296
Read More 4297
Read More 4298
Read More 4299
Read More 4300
Read More 4301
Read More 4302
Read More 4303
Read More 4304
Read More 4305
Read More 4306
Read More 4307
Read More 4308
Read More 4309
Read More 4310
Read More 4311
Read More 4312
Read More 4313
Read More 4314
Read More 4315
Read More 4316
Read More 4317
Read More 4318
Read More 4319
Read More 4320
Read More 4321
Read More 4322
Read More 4323
Read More 4324
Read More 4325
Read More 4326
Read More 4327
Read More 4328
Read More 4329
Read More 4330
Read More 4331
Read More 4332
Read More 4333
Read More 4334
Read More 4335
Read More 4336
Read More 4337
Read More 4338
Read More 4339
Read More 4340
Read More 4341
Read More 4342
Read More 4343
Read More 4344
Read More 4345
Read More 4346
Read More 4347
Read More 4348
Read More 4349
Read More 4350
Read More 4351
Read More 4352
Read More 4353
Read More 4354
Read More 4355
Read More 4356
Read More 4357
Read More 4358
Read More 4359
Read More 4360
Read More 4361
Read More 4362
Read More 4363
Read More 4364
Read More 4365
Read More 4366
Read More 4367
Read More 4368
Read More 4369
Read More 4370
Read More 4371
Read More 4372
Read More 4373
Read More 4374
Read More 4375
Read More 4376
Read More 4377
Read More 4378
Read More 4379
Read More 4380
Read More 4381
Read More 4382
Read More 4383
Read More 4384
Read More 4385
Read More 4386
Read More 4387
Read More 4388
Read More 4389
Read More 4390
Read More 4391
Read More 4392
Read More 4393
Read More 4394
Read More 4395
Read More 4396
Read More 4397
Read More 4398
Read More 4399
Read More 4400
Read More 4401
Read More 4402
Read More 4403
Read More 4404
Read More 4405
Read More 4406
Read More 4407
Read More 4408
Read More 4409
Read More 4410
Read More 4411
Read More 4412
Read More 4413
Read More 4414
Read More 4415
Read More 4416
Read More 4417
Read More 4418
Read More 4419
Read More 4420
Read More 4421
Read More 4422
Read More 4423
Read More 4424
Read More 4425
Read More 4426
Read More 4427
Read More 4428
Read More 4429
Read More 4430
Read More 4431
Read More 4432
Read More 4433
Read More 4434
Read More 4435
Read More 4436
Read More 4437
Read More 4438
Read More 4439
Read More 4440
Read More 4441
Read More 4442
Read More 4443
Read More 4444
Read More 4445
Read More 4446
Read More 4447
Read More 4448
Read More 4449
Read More 4450
Read More 4451
Read More 4452
Read More 4453
Read More 4454
Read More 4455
Read More 4456
Read More 4457
Read More 4458
Read More 4459
Read More 4460
Read More 4461
Read More 4462
Read More 4463
Read More 4464
Read More 4465
Read More 4466
Read More 4467
Read More 4468
Read More 4469
Read More 4470
Read More 4471
Read More 4472
Read More 4473
Read More 4474
Read More 4475
Read More 4476
Read More 4477
Read More 4478
Read More 4479
Read More 4480
Read More 4481
Read More 4482
Read More 4483
Read More 4484
Read More 4485
Read More 4486
Read More 4487
Read More 4488
Read More 4489
Read More 4490
Read More 4491
Read More 4492
Read More 4493
Read More 4494
Read More 4495
Read More 4496
Read More 4497
Read More 4498
Read More 4499
Read More 4500