Giter Site home page Giter Site logo

laravel-widgets's Introduction

Latest Stable Version Total Downloads Build Status Scrutinizer Quality Score

Widgets for Laravel

A powerful alternative to view composers. Asynchronous widgets, reloadable widgets, console generator, caching - everything that you can imagine.

Installation

Run composer require arrilot/laravel-widgets

Usage

Let's consider that we want to make a list of recent news and reuse it in several views.

First of all we can create a Widget class using the artisan command provided by the package.

php artisan make:widget RecentNews

This command generates two files:

  1. resources/views/widgets/recent_news.blade.php is an empty view.

Add "--plain" option if you do not need a view.

  1. app/Widgets/RecentNews is a widget class.
<?php

namespace App\Widgets;

use Arrilot\Widgets\AbstractWidget;

class RecentNews extends AbstractWidget
{
    /**
     * The configuration array.
     *
     * @var array
     */
    protected array $config = [];

    /**
     * Treat this method as a controller action.
     * Return view() or other content to display.
     */
    public function run()
    {
        //

        return view('widgets.recent_news', [
            'config' => $this->config,
        ]);
    }
}

Note: You can use your own stubs if you need. Publish config file to change paths.

The last step is to call the widget. There are several ways to do so.

@widget('recentNews')

or

{{ Widget::run('recentNews') }}

or even

{{ Widget::recentNews() }}

There is no real difference between these. The choice is up to you.

Passing variables to widget

Via config array

Let's carry on with the "recent news" example.

Imagine that we usually need to show five news, but in some views we need to show ten. This can be easily achieved by:

class RecentNews extends AbstractWidget
{
    ...
    protected array $config = [
        'count' => 5
    ];
    ...
}

...
@widget('recentNews') // shows 5
@widget('recentNews', ['count' => 10]) // shows 10

['count' => 10] is a config array that can be accessed by $this->config.

Config array is available in every widget method so you can use it to configure placeholder and container too (see below)

Note: Config fields that are not specified when you call a widget aren't overridden:

class RecentNews extends AbstractWidget
{
    ...
    protected array $config = [
        'count' => 5,
        'foo'   => 'bar'
    ];
    
    ...
}

@widget('recentNews', ['count' => 10]) // $this->config['foo'] is still 'bar'

Note 2: You may want (but you probably don't) to create your own BaseWidget and inherit from it. That's fine. The only edge case is merging config defaults from a parent and a child. In this case do the following:

  1. Do not add protected $config = [...] line to a child.

  2. Instead, add defaults like this:

public function __construct(array $config = [])
{
    $this->addConfigDefaults([
        'child_key' => 'bar'
    ]);

    parent::__construct($config);
}

Directly (works only for Laravel versions below 7)

You can also choose to pass additional parameters to run() method directly.

@widget('recentNews', ['count' => 10], 'date', 'asc')
...
public function run($sortBy, $sortOrder) { }
...

run() method is resolved via Service Container, so method injection is also available here.

Namespaces

By default, the package tries to find your widget in the App\Widgets namespace.

You can override this by publishing package config (php artisan vendor:publish --provider="Arrilot\Widgets\ServiceProvider") and setting default_namespace property.

Although using the default namespace is very convenient, in some cases you may wish to have more flexibility. For example, if you've got dozens of widgets it makes sense to group them in namespaced folders.

No problem, there are several ways to call those widgets:

  1. Pass a full widget name from the default_namespace (basically App\Widgets) to the run method.
@widget('News\RecentNews', $config)
  1. Use dot notation.
@widget('news.recentNews', $config)
  1. FQCN is also an option.
@widget('\App\Http\Some\Namespace\Widget', $config)

Asynchronous widgets

Sometimes it can be very beneficial to load widget content with AJAX.

Fortunately, this can be achieved very easily! All you need to do is to change facade or blade directive - Widget:: => AsyncWidget::, @widget => @asyncWidget

Widget params are encrypted (by default) and sent via ajax call under the hood. So expect them to be json_encoded() and json_decoded() afterwards.

Note: You can turn encryption off for a given widget by setting public $encryptParams = false; on it. However, this action will make widget params publicly accessible, so please make sure to not leave any vulnerabilities. For example, if you pass something like user_id through widget params and turn encryption off, you do need to add one more access check inside the widget.

Note: You can set use_jquery_for_ajax_calls to true in the config file to use it for ajax calls if you want to, but you need to manually add jquery to your page in this case.

By default, nothing is shown until ajax call is finished.

This can be customized by adding a placeholder() method to the widget class.

public function placeholder(): string
{
    return 'Loading...';
}

Side note: If you need to do something with the routes package used to load async widgets (e.g. you run app in a subfolder http://site.com/app/) you need to copy Arrilot\Widgets\ServiceProvider to your app, modify it according to your needs and register it in Laravel instead of the former one.

Reloadable widgets

You can go even further and automatically reload widget every N seconds.

Just set the $reloadTimeout property of the widget class and it is done.

class RecentNews extends AbstractWidget
{
    /**
     * The number of seconds before each reload.
     *
     * @var int|float
     */
    public $reloadTimeout = 10;
}

Both sync and async widgets can become reloadable.

You should use this feature with care, because it can easily spam your app with ajax calls if timeouts are too low. Consider using web sockets too but they are way harder to set up.

Container

Async and Reloadable widgets both require some DOM interaction so they wrap all widget output in a html container. This container is defined by AbstractWidget::container() method and can be customized too.

/**
 * Async and reloadable widgets are wrapped in container.
 * You can customize it by overriding this method.
 *
 * @return array
 */
public function container(): array
{
    return [
        'element'       => 'div',
        'attributes'    => 'style="display:inline" class="arrilot-widget-container"',
    ];
}

Note: Nested async or reloadable widgets are not supported.

Caching

There is also a simple built-in way to cache entire widget output. Just set $cacheTime property in your widget class and you are done.

class RecentNews extends AbstractWidget
{
    /**
     * The number of minutes before cache expires.
     * False means no caching at all.
     *
     * @var int|float|bool
     */
    public $cacheTime = 60;
}

No caching is turned on by default. A cache key depends on a widget name and each widget parameter. Override cacheKey method if you need to adjust it.

Cache tagging

When tagging is supported (see the Laravel cache documentation) and to simplify cache flushing, a tag widgets is assigned by default to all widgets. You can define one or more additional tags to your widgets by setting the values in the $cacheTags property in your widget class. Example :

class RecentNews extends AbstractWidget
{
    /**
     * Cache tags allow you to tag related items in the cache 
     * and then flush all cached values that assigned a given tag.
     *
     * @var array
     */
    public array $cacheTags = ['news', 'frontend'];
}

For this example, if you need to flush :

// Clear widgets with the tag news
Cache::tags('news')->flush();

// Clear widgets with the tag news OR backend
Cache::tags(['news', 'frontend'])->flush();

// Flush all widgets cache
Cache::tags('widgets')->flush();

Widget groups (extra)

In most cases Blade is a perfect tool for setting the position and order of widgets. However, sometimes you may find useful the following approach:

// add several widgets to the 'sidebar' group anywhere you want (even in controller)
Widget::group('sidebar')->position(5)->addWidget('widgetName1', $config1);
Widget::group('sidebar')->position(4)->addAsyncWidget('widgetName2', $config2);

// display them in a view in the correct order
@widgetGroup('sidebar')
// or 
{{ Widget::group('sidebar')->display() }}

position() can be omitted from the chain.

Widget::group('sidebar')->addWidget('files');

equals

Widget::group('sidebar')->position(100)->addWidget('files');

You can set a separator that will be display between widgets in a group. Widget::group('sidebar')->setSeparator('<hr>')->...;

You can also wrap each widget in a group using wrap method like that.

Widget::group('sidebar')->wrap(function ($content, $index, $total) {
    // $total is a total number of widgets in a group.
    return "<div class='widget-{$index}'>{$content}</div>";
})->...;

Removing widgets from a group

There is a couple of ways to remove widget/widgets from a group after they've been already added.

  1. Remove one widget by its unique id
$id1 = Widget::group('sidebar')->addWidget('files');
$id2 = Widget::group('sidebar')->addAsyncWidget('files');
Widget::group('sidebar')->removeById($id1); // There is only second widget in the group now
  1. Remove all widgets with specific name
Widget::group('sidebar')->addWidget('files');
Widget::group('sidebar')->addAsyncWidget('files');
Widget::group('sidebar')->removeByName('files'); // Widget group is empty now
  1. Remove all widgets that are placed on a specific position.
Widget::group('sidebar')->position(42)->addWidget('files');
Widget::group('sidebar')->position(42)->addAsyncWidget('files');
Widget::group('sidebar')->removeByPosition(42); // Widget group is empty now
  1. Remove all widgets at once.
Widget::group('sidebar')->addWidget('files');
Widget::group('sidebar')->addAsyncWidget('files');
Widget::group('sidebar')->removeAll(); // Widget group is empty now

Checking the state of a group

Widget::group('sidebar')->isEmpty(); // bool

Widget::group('sidebar')->any(); // bool

Widget::group('sidebar')->count(); // int

Namespaces for third party packages (extra)

In some cases, it may be useful to deliver widgets with your own packages. For example, if your package allows you to manage news, it would be convenient to have immediately configurable widgets, ready for display, directly delivered with your package.

To avoid having to use the fqcn each time, you can set a widget namespace into your package provider. This way the widgets from your package can be more easily identified, and especially the syntax will be shorter.

To do that, all you have to do is to register the namespace in your package service provider :

public function boot() 
{
    app('arrilot.widget-namespaces')->registerNamespace('my-package-name', '\VendorName\PackageName\Path\To\Widgets');
}

After that you can use the namespace in your views :

@widget('my-package-name::foo.bar')

// is equivalent to
@widget('\VendorName\PackageName\Path\To\Widgets\Foo\Bar')

laravel-widgets's People

Contributors

arrilot avatar buzzclue avatar clarence-pan avatar ifnotfr avatar lex111 avatar mintunitish avatar robertboes avatar sakalauskas avatar sebastienheyd avatar wuwx avatar yajra avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laravel-widgets's Issues

Question - Push new data to widget

This is a brilliant library, I was wondering if there is anyway to make the Re-loadable widget query a data set for changes before reloading?

CacheKey

In the docs, it mentions that there is a cache key used that is based "on a widget name and each widget parameter" and digging in the code, it is not exactly clear what it is set to by default.

Is there a way to get an example for the RecentNews widget used throughout the docs?

Like if we want to clear the cache, do we do something like Cache::forget('recentNews')? Or is there something more it is based on?

Cache::forget('arrilot.widgets.recentNews')?

** Update...so digging in further, cause this is really interesting to me. You would have to do something like this:

Cache::forget('arrilot.widgets.'serialize(['recentNews', ['count' => 5]])

That seems to work (well, not 100% that, but something similar) for me in this project I am working on. Would be nice if we could set some simpler cache things that we could easily clear out cache for a widget. But there is a consideration of multiple templates using the widget in different ways, which is why you are serializing all the params instead of just the name.

Like in one layout, you have ['count' => 5] and another one you have ['count' => 10']. These are different caches, and you wouldn't necessarily want to clear out both.

What about something like

@widget('recentNews', ['count' => 5, 'cacheKey' => 'myUniqueKey']

Then in AbstractWidget.php

public function cacheKey(array $params = [])
    {
        // untested psuedo-code
        if(array_key_exists('cacheKey', $params[1])) {
                    return 'arrilot.widgets.'$params[1]['cacheKey']';
        }
        return 'arrilot.widgets.'.serialize($params);
    }

This (should) set the Cache key to arrilot.widgets.myUniqueKey that you could access anywhere.

I'm open to some discussion on this, and would be willing to work on it, let me know your thoughts.

Send variable parameter(input)?

How could I send a variable parameter (input) for the widget , such as:
@widget('recentNews', ['count' = > 10] , 'date' , $("#InputOrder"))

It is possible?

Thank you.

Autoloading wot working for me

Hi,
I liked the widget you provide, and I want to use it, very simple and useful, my only problem is the autoloading, I'm working with Laravel 4.2 and laravel-widgets version ~1.0.

I created a widget using php artisan make:widget StatsDash, I added to composer.json I have

...
"app/database/
"app/tests/TestCase.php"
"app/Widgets/StatsDash.php"

I works well, but I want to add the Widgets folder to my project, so I dont need to add each time my new widget, so I used PSR-0

"psr-0":{
    "Widgets": "app/",
}

after that I used : composer dumpautoload I got : 'Class 'App\Widgets\StatsDash' not found'

Thank you for helping

Publish 2 widgets

I created 2 widgets, and when I try to display them, I got only one, for example:

{{ Widget::widgetOne() }}
{{ Widget::widgetTwo() }}

It shows only widgetOne , And when I delete the widgetOne I can see widgetTwo

Why ?

[L5] Can't load widgets

When I try to load the widget in my view I get the following error

**
Symfony\Component\Debug\Exception\FatalErrorException thrown with message "Method Illuminate\View\View::__toString() must not throw an exception"

Stacktrace:
#0 Symfony\Component\Debug\Exception\FatalErrorException in C:\Users\Curtis\Code\laravel\cloudlite\vendor\arrilot\laravel-widgets\src\Factories\AbstractWidgetFactory.php:0

**

Widget class must extend Arrilot\Widgets\AbstractWidget class

I was having trouble getting Widgets work on Laravel 5.1. My app runs throw ErrorException, this is it:

ErrorException in AbstractWidgetFactory.php line 122:
Widget class must extend Arrilot\Widgets\AbstractWidget class (View: /home/vagrant/Code/Laravel/resources/views/welcome.blade.php)

My Widget Class was created with artisan command 'artisan make:widget Input'
and it extends AbstractWidget from Arrilot\Widgets\AbstractWidget. So here is class:

<?php namespace App\Widgets;

use Arrilot\Widgets\AbstractWidget;

class Input extends AbstractWidget {
    protected $config = [
        'type' => 'text'
    ];
    public function run()
    {
        return view("widgets.input", [
            'config' => $this->config,
        ]);
    }
}

What can it be?
Thanks!

Rework config array in 3.0

  1. Current implementation:
class RecentNews extends AbstractWidget 
{
    protected $count = 5;
    protected $foo;

    public function run($sort_by, $sort_order) { return $this->count;}
}
...
@widget('recentNews', [
       'count' => 10,
       'foo'     => 'bar'
], 'date', 'asc')
  1. Proposal №1: Remove config array completely because now it's possible to pass parameters directly to run function

  2. Proposal №2: Store config in a single property.

class RecentNews extends AbstractWidget 
{
    protected $config = [
          'count' => 10, 
    ];

    public function run($sort_by, $sort_order) { return $this->config['count'];}
}
...
@widget('recentNews', [
       'count' => 10,
       'foo'     => 'bar'
], 'date', 'asc')

Any feedback appreciated.

Determine if a widget group has anything set

Is there a way to determine if the widget group has anything set to be displayed? This is a awesome package but it would be nice if you could determine easily if anything is inside the widget group so that maybe something else could be set along with it. I wanted to setup the side bar column widths (using bootstraps col css) if something is inside of the Widget::group('sidebar'). if not than the content area width would be full width.

2 or more AsyncWidget in one place.

Hi! I wonder, why it's happens. If I set in blade smth like that:
{{ AsyncWidget::News() }}
{{ AsyncWidget::trendingNow() }}

Render return me in some case only one widget, in some case return me in both widget the same content. Can you help me with it?! Thanks.

FYI: I've set this config: "use_jquery_for_ajax_calls" to true, in this file "vendor/arrilot/laravel-widgets/src/config/config.php" and all works fine now.

Assync container not incrementing the id

When I set a reloadTimeout on my widget it only gets updated once and then I got this error on the js console:

Cannot set property 'innerHTML' of null

When I inspect the javascript I can see its looking for an element with an id of 'arrilot-widget-container-3' but my widget wrapper is still on 'arrilot-widget-container-2'.

Edit:
I think I was doing something I was not supposed. I had one widget rendering another, that was the source of the error.
The assync one was the 'parent'.

question about config array

the example in readme.md says

class RecentNews extends AbstractWidget {
    ...
    protected $config = [
        'count' => 5,
        'foo'   => 'bar'
    ];

    ...
}

@widget('recentNews', ['count' => 10]) // $this->config('foo') is still 'bar'

however I found some problem.

  1. there is no method config in AbstractWidget. so maybe the last comment should be // $this->config['foo'] is still 'bar'
  2. I found the example didn't work, so I read the code in WidgetFactory and AbstractWidget. The params pased to the construct function were set as properties instead of values of confi array. so is the doc out of date or I made some mistake?

How can I get all existing widgets list ?

I have created 3 widgets for now, and I want to know dynamically (in controller) all the names of existing widgets,so that i can display their name. What is the possibility to do so ?

[Enhancement] add a path for stubs

Is it possible to add stubs to config file ?

for example

<?php
return [
    //'default_namespace' => 'App\Widgets',
    'stubs' => [
         'widget' => app_path() . '/vendor/arrilot/laravel-widgets/src/Console/stubs/widget.stub',
         'widget_plain' => app_path() . '/vendor/arrilot/laravel-widgets/src/Console/stubs/widget_plain.stub',
    ],
    'use_jquery_for_ajax_calls' => false,
];

it will allow us to customize easily stubs

How use it from wysiwyg editor?

I try use widget in wysiwyg, but it doesn't work. I use this code {!!Widget::Menu(['type' => 'top'])!!}
Sorry for my English )

Error when using Widget group

i got an error when using widget group

Class 'Arrilot\Widgets\Misc\Wrapper' not found

and i try to inspect your code and found file naming with LaravelApplicationWrapper instead Wrapper, and i change the Class in WidgetGroup.php with LaravelApplicationWrapper.

and also the
appMake()

method that use in WidgetGroup.php on line 112 to

make()

i hope you can fix this.
thanks for the awesome package

Can't do dependency injection

I try to do dependency injection

private $categoriesMenuRenderer;

    public function __construct(CategoriesMenuRenderer $categoriesMenuRenderer)
    {
        parent::__construct();
        $this->categoriesMenuRenderer = $categoriesMenuRenderer;
    }

but I get an error

Type error: Argument 1 passed to Modules\Articles\Http\Controllers\CategoriesMenu::__construct() must be an instance of Modules\Articles\Services\CategoriesMenuRenderer, array given

I can't realise what am I doing wrong? In PublicController dependency injection works

Widget begin & end

In addition to a Widget::run() which outputs a chunk of html to the view, a Widget::begin() & Widget::end() would be handy for encapsulating existing view logic, without the need to store that resulting logic into a variable.

For example:

{{ Widget::begin('Panel', ['title' => 'Foo', 'actions' => []]) }}
<h1>Content Title</h1>
{{ Widget::end() }}

Additionally you can wrap begin & end widgets recursively if needed.

I use this extensively in my own work and find it quite useful. Happy to submit a pull request.

Real-time widgets

Is it possible to have real-time(ish) widgets that update every x ms? If not, this would be really cool to add, as it is exactly what I need.

Great package nonetheless, very clean code.

How to parse custom data.

Hi, My english is a bit poor. I am sorry for this.
I do not have any problems viewing the parsing inside the blade file. But custom created variables not working.

MainNavigation Widget:

`<?php

namespace App\Widgets;

use Arrilot\Widgets\AbstractWidget;
use App\Module;

class MainNavigation extends AbstractWidget
{
/**
* The configuration array.
*
* @var array
*/
protected $config = [];

/**
 * Treat this method as a controller action.
 * Return view() or other content to display.
 */
public function run()
{
    $modules = Module::get();
    
    return view("widgets.main_navigation", [
        'navigation' => $modules,
    ]);
}

}`

Widget::run('mainNavigation', $navigation)

main_navigation.blade.php

dd($navigation)

result

Undefined variable: navigation.

How can I solve this problem? Where am I doing wrong?

My laravel version: 5.3

Thanks.

Static widgets

Is it possible to add static widgets without class create?

Question - Howto set reload interval from config

How can i assign a config var to reloadTimeout ?

i tried to set config('app.reload') to reloadTimeout, however this gives me the error.

FatalErrorException in RecentTasks.php line 25:
Constant expression contains invalid operations

How can I call Widget from controller action ?

Calling widget from view for e.g. {!! Widget::recentNews() !!} was successful, but calling Widget::recentNews() gives an error

<<
Class 'App\Http\Controllers\Widget' not found

Please suggest.

Laravel 5.4 support

Hello!
Are you going to release a new version which supports laravel 5.4?

How to call asyncwidget

If I add AsyncWidget::widgetexample(); it is loaded on boot.
But how can I call it again without refreshing the page?

Async Loading

At first, thank you for this great package. It work's really well. How do i have to implement the async Loading in my view? If i use the AsyncWidget i only see the placeholder, my run ist never returned... What do i miss?

THanks
Jens

feature request calling other methods other than run of widget

Hi, right package widget is calling run method of widget class, can you improve it to call other public method of the same widget, like news widget run is main method which is getting latest news, if we want to get popular news you need to create new widget for popular news, i think no need to create a new widget when news widget is already there just add method popularNews

{{ Widget::run('recentNews:popularNews') }}
or
{{ Widget::recentNews(['method'=>'popularNews']) }}
or
@widget('recentNews:popularNews')

contributing?

Whats your process for contributing new features/bugfixes? I've created my own AbstractWidget to resolve a couple of niggling issues I've dealt with which may be beneficial to the base package.

Are you happy to accept issues + approve + pull requests?

Last release matcher is broken

I was using the following widget configuration, and it has been broken on the last release:
@widget('VideosWidget', ['type' => 'important', 'user' => auth()->user(), 'title' => 'Fontos videók az elmúlt 30 napból:)', 'days' => 30])
after fixing the :)' part, everything was working fine, guess the matcher is not working so well, or I do not know. Fixed code
@widget('VideosWidget', ['type' => 'important', 'user' => auth()->user(), 'title' => 'Fontos videók az elmúlt 30 napból', 'days' => 30])

PHP Fatal error: Maximum function nesting level of '256' reached, aborting!

I am getting a PHP Fatal Error exception when running php artisan make:widget RecentNews, after going through the installation steps as described here.

PHP Fatal error: Maximum function nesting level of '256' reached, aborting! in .../vendor/laravel/framework/src/Illuminate/Container/Container.php on line 698
PHP Fatal error: Maximum function nesting level of '256' reached, aborting! in .../vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php on line 115
Full command output can be found as an attachment to this post.

Increase the value of xdebug.max_nesting_level in the php.ini (to 500, f.e.) did not help. It then told me it reached maximum function nesting level '500'.

php artisan make:model test runs without any issues.

I am running php 7.0.8-2+deb.sury.org~xenial+1 and using laravel 5.3.

What am I doing wrong? Or how can I solve this?
PHP Fatal error.txt

Inheritance config problem

I'm creating a lot of widgets that extend from abstract widgets that i've created. The problem with this is because the config of a widget is stored under a single property protected $config = [], my concrete classes don't have an easy ability to set a base line config that inherits from the parent.

As a work around, i have to do something like this (crude example):

class MyListWidget extends BaseListWidget
{
    // can't declare property $config here otherwise it completely wipes out the base config

    public function __construct(array $config = [])
    {
        $defaults = [
          'classes' => 'base-list my-base-list'
        ];
        $this->config = array_merge($this->config, $defaults);
        parent::__construct($config);
    }
}

abstract class BaseListWidget extends Arrilot\Widgets\AbstractWidget 
{
    protected $config = [
      'data' => [],
      'classes' => 'base-list', 
    ];

    public function run()
    {
    }
}

This creates a lot of bootstrap to extend from the base config, and can create more problems with bigger inheritance chains (especially if you get the order of the merge mixed up..).

It would be better if each config option was a seperate public property. During the constructor, it would be quite easy to detect public properties and make those the key for the config.

Because this would be fundamentally changing how the widgets set their config, you could prioritise public properties over the config property, thus maintaining backwards compatibility.

Additionally a convenience getter/setter makes the location of the config irrelevant.

Happy do submit a pull request if you think this is suitable.

[Enhancement] choose a custom path when creating a widget with make:widget command

it would be great if we could change the widgets directory, I think that right now you are using the name space to define in which directory you create a widget, but in my use case the default_namespace doesn't reflect the directory

Example :

my app is separated into two levels, the core of the application and the custom part

to simplify I have this architecture :


./core (which contain laravel project)
  ./app : namespace AppName\
  ./storage 
  ./ ...
./widgets : namespace AppName\Widgets

composer helps me to maintain all this things ok, so if I create manually a widget into ./widgets I can use it without problem, but I can't use the make:widgetcommand because it will create a ./core/app/Widgets/RecentNews.phpinstead of ./widgets/RecentNews.php

So the idea is to have the possiblity to choose the path in which we create our widgets.

<?php

return [
    'default_namespace' => 'App\Widgets',
    /* ... */
    'default_path' => custom_path('widgets'),
];

<span> container

Package adds wrapping span tags like <span id="arrilot-widget-container-7" class="arrilot-widget-container"> around widget content.
If inside this tags will be placed <div> tags, the page becomes invalid for w3c validator.

Maybe it's better use another tags for it?

Widget group not being collected on main widget factory instance.

When creating a group widget using the main factory, the groups are not being collected because the factory is using bind which always creates a new instance when using app('arrilot.widget'). To fix this, I suggest to update the provider to use singleton.

        $this->app->singleton('arrilot.widget', function () {
            return new WidgetFactory(new LaravelApplicationWrapper());
        });

Example snippet to replicate the issue:

        Widget::all()->groupBy('position')->each(function (Collection $group) {
            $group->each(function ($widget) {
                $factory = app('arrilot.widget');
                $factory->group($widget->position)
                        ->addWidget('widgetManager', [], $widget);
            });
        });

To display:

@widgetGroup('left')
@widgetGroup('right')

Blade stack / push

Hi,
i have a problem with stack and push directives.
I have a page with header and directive @stack('css') in it. When i put a widget with @Push('css') ... @endpush on a page nothing is reflected in @stack inside header. If @stack directive is put on a page after @widget directive, @Push is reflected as supposed to.
So, if stack is before widget, nothing happens, if stack is after widget works as expected.
What can i do to to solve the problem?

Thanks

Rendering widgets without generated container

Hello, I have a problem with the widgets while rendering. On this stage a container is placed, inside of which the view output is rendered. This container, however, sometimes breaks the layout, for example in lists used with dropdown menus.

Is it possible to control this behavior of the widget?

PS: I assume this is used with reload feature and async widgets, but could it be ignored for static widgets?

Allow sub-namespaces

In my application, I have a clear separation of frontend and backend code. Thus, I want to separate widgets designed for frontend from those designed for backend.

For this, I've tried to move generated widget class into sub-folder called "Frontend" and changing it's namespace.

But this does not work, and I receive Widget class must extend Arrilot\Widgets\AbstractWidget class exception.

Once I move widget to root "Widgets" directory it is working again.

Problem with @section

I have widget with:
...
return view("widgets.user_list");

user_list.blade.php extends another blade file(widget.blade.php) which has @yield('content') in it.
The point is to make HTML wrapper for the widget. The HTML in widget.blade.php does not appear, I see only the actual widget file user_list.blade.php.

Broken with latest BladeCompiler changes

With latest changes, createMatcher() is removed from Blade

FatalErrorException in ServiceProvider.php line 89:
Call to undefined method Illuminate\View\Compilers\BladeCompiler::createMatcher()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.