Comments (8)
Hi, I thanks for the feedback. I have to look into editing (un)ordered lists, I think it is because they are not editable as a whole or CKEditor changes it into a paragraph tag or something. What I do is I have in my laravel project a simple menu builder (for example with nestable). Then, I use a .php block that loads all items of the menu stored in the database, so I do not have to edit the menu manually from within the pagebuilder (on every page).
As you can see in this image, it should be possible to edit a css background image.
I think you mean creating custom layouts from within your application (similar to the master layout) and then add some default blocks. That is indeed very helpful. I have it in my platform that integrates the pagebuilder, so it certainly is already possible to build this on top of the pagebuilder.
I have a separate page_layouts
table that has the same structure as the pages
table. This is the controller action that I am using:
public function buildLayout($pageLayoutId = null)
{
$route = $_GET['route'] ?? null;
$action = $_GET['action'] ?? null;
// override settings to use the pagebuilder on layouts instead of pages
config([
'pagebuilder.pagebuilder.url' => '/admin/website/page-layouts/build',
'pagebuilder.pagebuilder.actions.back' => '/admin/website/page-layouts',
'pagebuilder.page.class' => \PHPageBuilder\Page::class,
'pagebuilder.page.translation.class' => \PHPageBuilder\PageTranslation::class,
'pagebuilder.page.table' => 'page_layouts',
]);
// refresh the PhpPageBuilder singleton with the updated config
app()->extend('phpPageBuilder', function ($command, $app) {
return new PHPageBuilder(config('pagebuilder'));
});
// get the page layout as Page object
$pageLayoutId = is_numeric($pageLayoutId) ? $pageLayoutId : ($_GET['page'] ?? null);
$pageRepository = new PageRepository;
/* @var PageContract $pageLayout */
$pageLayout = $pageRepository->findWithId($pageLayoutId);
/* @var PHPageBuilder $phpPageBuilder */
$phpPageBuilder = app()->make('phpPageBuilder');
$pageBuilder = $phpPageBuilder->getPageBuilder();
$customScripts = view("website::pagebuilder.scripts")->render();
$pageBuilder->customScripts('head', $customScripts);
$pageBuilder->handleRequest($route, $action, $pageLayout);
}
And I have an class that overrides the PageRenderer, in order to render the layout.
The code is not fully copy pastable, since I am using certain repositories that I created, but it gives an idea of how I use it.
use Exception;
use Falco\Website\Repositories\PageLayoutRepository;
use PHPageBuilder\Contracts\PageContract;
use PHPageBuilder\Page;
use PHPageBuilder\ThemeBlock;
class PageRenderer extends \PHPageBuilder\Modules\GrapesJS\PageRenderer
{
/**
* Return the rendered version of the page.
*
* @return string
* @throws Exception
*/
public function render()
{
// init variables that should be accessible in the view
$renderer = $this;
$page = $this->page;
if ($this->forPageBuilder) {
$body = '<div phpb-content-container="true"></div>';
} else {
$body = $this->renderBody();
}
// recursively render page layouts in which the page body will be added
list($layoutPath, $body) = $this->renderLayouts($page, $this->getPageLayoutPath(), $body);
if ($layoutPath) {
ob_start();
require $layoutPath;
$html = ob_get_contents();
ob_end_clean();
} else {
$html = $body;
}
// parse any shortcodes present in the page layout
$html = $this->parseShortcodes($html);
return $html;
}
/**
* Recursively render all nested layouts, starting from the outer layout with finally a configured base layout from the current theme.
*
* @param PageContract $parent
* @param $parentLayoutPath
* @param $renderedParentBody
* @return array
* @throws Exception
*/
protected function renderLayouts(PageContract $parent, $parentLayoutPath, $renderedParentBody)
{
// render the layout if a page_layout_id is passed, or the layout field has a numeric value (so it contains reference to a custom page layout)
if ((is_null($parent->getLayout()) && ! empty($parent->page_layout_id)) || is_numeric($parent->getLayout())) {
$pageLayoutId = $parent->page_layout_id ?? $parent->getLayout();
$pageLayout = (new PageLayoutRepository)->findOneByField('id', $pageLayoutId);
// create a new page renderer to render the page layout (in an empty parent layout)
$layoutPage = new Page;
$layoutPage->setData([
'layout' => null,
'data' => json_decode($pageLayout->data, true)
]);
$layoutRenderer = new PageRenderer($this->theme, $layoutPage, $this->forPageBuilder);
$layoutBody = $layoutRenderer->renderBody();
// replace the layout main container with the page body or body of a parent layout
$layoutMainContainerBlock = new ThemeBlock($this->theme, 'layout-main-container');
$layoutMainContainerBlockViewFile = $layoutMainContainerBlock->getViewFile();
$layoutMainContainerString = file_get_contents($layoutMainContainerBlockViewFile);
$body = str_replace($layoutMainContainerString, $renderedParentBody, $layoutBody);
// render layouts in which this layout or page body is contained
$layoutPath = $this->theme->getFolder() . '/layouts/' . $pageLayout->layout . '/view.php';
$layoutPage->setData(['layout' => $pageLayout->layout]);
list($layoutPath, $body) = $this->renderLayouts($layoutPage, $layoutPath, $body);
}
// eventually return the base layout (a layout folder of the current theme) of the inner most page layout, and the final page body that combines all layouts
return [$layoutPath ?? $parentLayoutPath, $body ?? $renderedParentBody];
}
}
Next, I replaced the PageRenderer class by specifying a class replacement in the phpagebuiler config file.
'class_replacements' => [
PHPageBuilder\Modules\GrapesJS\PageRenderer::class => Falco\Website\Libraries\PHPageBuilder\PageRenderer::class
],
from laravel-pagebuilder.
nice, thank you for the code!
what i meant is, i cant edit the text inside the block which has a background image.
i found out its not possible to put a block inside a block or did i miss something?
i created some "general" blocks like column, text, button and so on and tried to put the text or button block inside the colulmn, but thats not possible :(
from laravel-pagebuilder.
In my screenshot I have a text-editable block with a background image, so it should be a problem with your specific block html structure. I just used a block with a view.html which contains a <p>
tag with some example text.
You cannot just drop blocks everywhere, but you can create a blocks container in which it is possible to drop blocks. You create a blocks container by following these steps.
from laravel-pagebuilder.
I reproduced the problem with li tags being removed and I just committed a fix.
from laravel-pagebuilder.
I am trying to integrate the layouts table as you detailed above.
I was wondering if you could give an example of what to use inside of PageLayoutRepository and the master layout file view.php? Also, where does the helper method findOneByField come from as Laravel 6 is giving me a hard time with it?
Cheers,
Billie
from laravel-pagebuilder.
You are correct, I see that method is part of the boilerplate I am working with, the findOneByField does this:
public function findOneByField($field, $value = null, $columns = ['*'])
{
$model = $this->findByField($field, $value, $columns = ['*']);
return $model->first();
}
So just a findByField with a first.
PageLayoutRepository is a simple class I use that allows an abstraction for CRUD on page layouts (with some customization for my use cases). In standard Laravel a PageLayout class extending the base eloquent Model class would also work just fine.
This is a simplified version of my current master layout:
<!DOCTYPE html>
<html lang="<?= phpb_current_language() ?>">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title><?= e($page->getTitle()) ?></title>
<meta name="description" content="<?= e($page->getMetaDescription()) ?>">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="csrf-token" content="<?= e(csrf_token()) ?>">
<link rel="stylesheet" href="<?= themeAssetVersion('css/app.css') ?>">
</head>
<body>
<?= $body ?>
<script src="<?= themeAssetVersion('js/app.js') ?>"></script>
<!-- Run block scripts -->
<script type="text/javascript">
document.querySelectorAll("script").forEach(function(scriptTag) {
scriptTag.dispatchEvent(new Event('run-script'));
});
</script>
<?php
foreach ($page->get('custom-scripts-urls') ?? [] as $scriptUrl):
echo '<script src="' . e($scriptUrl) . '"></script>';
endforeach;
?>
</body>
</html>
themeAssetVersion is a simple helper method I use to bust outdated cached css/js files:
/**
* Return the theme asset path with a version GET parameter based on the latest file change.
*
* @param $assetPath
* @return string
*/
function themeAssetVersion($assetPath)
{
$theme = config('pagebuilder.theme.active_theme');
$themeFolder = config('pagebuilder.theme.folder') . '/' . $theme;
$fullAssetPath = $themeFolder . '/public/' . $assetPath;
if (realpath($fullAssetPath)) {
$modifiedTime = filemtime($fullAssetPath);
return url(phpb_theme_asset($assetPath) . '?v=' . $modifiedTime);
}
return url(phpb_theme_asset($assetPath));
}
Ignoring this method and using phpb_theme_asset intead would also work just fine.
from laravel-pagebuilder.
@HansSchouten
Thank you so much. I will work on this straight away and can't wait to see how it works. Cheers Hans!
from laravel-pagebuilder.
@HansSchouten can i please update CKeditor
becouse this dont have option for listi
from laravel-pagebuilder.
Related Issues (20)
- Migration Error HOT 5
- Can't run php artisan migrate HOT 3
- unable to add bullets in PB editor HOT 1
- Error when run migrate in laravel 8 in version phpbuildier 0.22.0
- pagebuilder HOT 1
- Migration error [Laravel 8.8, pagebuilder 0.24] HOT 3
- database mess
- You pushed Laravel library 3 years ago. Do you believe, this library will work on Laravel 10? HOT 3
- SQLSTATE[42S22]: Column not found: 1054 Unknown column 'meta_title' in 'field list' HOT 2
- How can I get Grapejs default block components inside my block HOT 2
- Tutorial about integrating PHPageBuilder into a Laravel project HOT 1
- Call to a member function select() on null Error
- Cannot drag & drop, white screen with nothing to do HOT 2
- No publishable resources for tag [config]. HOT 6
- No publishable resources for tag [config] HOT 2
- Issue on block separation using tailwind CSS HOT 2
- /admin not found, but records url as /in
- Admin Login returns 419 Expired
- incompatibility with laravel 10 and 11
- how do i implement this app with already having admin route and lots of users.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from laravel-pagebuilder.