OctoberCMS | access to static page property from component - php

There are some way to extract values from extra-fields of static pages into some component?
I need that to implement AJAX handlers...
I can load the static page content but, I need to get properties that was setted by user...
I need some example of code... I can load the static page content as a Partial
#noobhacks :)
public function onOpenHome()
{
$this->page['categories'] = Category::all();
return [
//'main' => $this->renderPartial('home'),
'main' => $this->renderPartial('../content/static-pages/index'),
'.home_categories' => $this->renderPartial('work_list_categories_post')
];
}
or as content:
[viewBag]
==
<main class="home_container" __color="{{ color }}">
<section class="box">
{% content '/static-pages/index.htm' %} <!-- <<<<------ -->
{{ content |raw }}
</section>
</main>
But I have no ideia how to access to property of colorpicker color

Component objects are available using their name (or alias). This means the value of "color" should be available via {{ viewBag.color }}.

Related

OctoberCMS global page properties?

Is it possible to set a series of global properties (such as social media usernames) that are available to all page views in OctoberCMS rather than having them associated to one CMS page or Static Page at a time?
For example, being able to use {{ twitter_username }} in any template, but it wouldn't show up as a field in any page form on the backend.
UPDATE: this can be achieved by registering a Twig function using registerMarkupTags in your plugin:
use System\Classes\PluginBase;
class Plugin extends PluginBase
{
public function registerMarkupTags()
{
return [
'functions' => [
'globals' => function($var) {
switch ($var) {
case 'twitter_username':
return 'mytwitterusername';
}
return null;
},
],
];
}
}
In this case, calling {{ globals('twitter_username') }} from any template prints mytwitterusername.
Hmm yes better you need to add code to life-cycle method in layouts, so now page which are using that layout will have this info already loaded.
In layout code block you can use something like this
use RainLab\Pages\Classes\Page as StaticPage;
function onStart() {
$pageName = 'static-test'; // this will be static page name/filename/title
$staticPage = StaticPage::load($this->controller->getTheme(), $pageName);
$this['my_title'] = $staticPage->viewBag['title'];
$this['twitter_username'] = $staticPage->viewBag['twitter_username'];
}
now inside your cms page you can use this variable
<h1>{{ my_title }} </h1>
<h3>{{ twitter_username }} </h3>
let me know if it you find any issues
You could also use theme config file which gives you more flexibility rather than hardcoding the values in to the code block.
https://octobercms.com/docs/themes/development#customization

OctoberCMS. How to pass variable from page to component?

I have defined a variable in a page:
{% set service = builderDetails.record %}
and I want to pass this variable to a component:
{% component 'Variations' service=service %}
but this method does not work. How can I do that?
I am guessing that you need to pass builderDetails.record to your component 'Variations'
and then you want to access that variables inside component 'Variations''s default.htm and show some details about it.
for that you need to utilize component's onRender method
inside your component 'Variations'
public function onRender()
{
$this->page['record'] = $this->page->components['builderDetails']->record;
}
$this->page->components is holding all the components available in page as array.
builderDetails is alias of the component Record Details(Builder Plugin) which is added in to page.
now inside your default.htm
you can access record variable and use it as you desire
{{ record.name }}
we assume here that your record has attribute name
if you need anything please comment.
In a Twig .htm partial
<div class="sidebar-widget">
{% component "postBlock" score=55 name="Johan" %}
<div class="nonsense meta">
{% partial 'nonsense' score=75 name="Marga" %}
</div>
</div>
In the nonsense twig that is a child of the previous .htm partial
<div class="sidebar-element">
<div>My name is: {{ name|default('John Doe') }}</div>
<div>My score is: {{ score|default('No score') }}</div>
</div>
In the component postBlock, onRender function
function onRender() {
$score = $this->property('score'); // 55
$name = $this->property('name'); // Johan
}
To pass from a parent twig to a child twig, you don't have to use the onRender function
in the component, only if you want to modify things and pass is from there to the twig.
You dont have to assign it to page. You can access it via:
__SELF__.property('property_name')
After definin property in component:
{% component 'Variations' service=service %}
In your components default.htm
{{__SELF__.property('service')}}

ezplatform render links with url and object name from multi-relational content item in content type

does anyone know now to create a custom view type for ez platform? The default 3 have been exhausted and we need a new one for 'link'
Alternatively, does anyone know how to use the render( controller( with a custom template as this would also resolve out block right now.
Basically, we have a multi-relational field in a content object used and we need to print links to all the related contentIds, path works great but we cannot find a way to extract the name of the content object for the link without doing some fairly funky tpl logic of passing in params.
EG: As a hack for now we can pass in "embed_type" as a custom param with the render(controller("ez_content:viewAction" to pull in an alternate view for the content object for a specific content type and view type.
{% if embed_type is defined %}
{% include "embed/#{embed_type}.html.twig" %}
{% else %}
<h1>{{ ez_field_value( content, 'name') }}</h1>
{% endif %}
However, this is very ugly and all we really want to do is use 1 template for all content types, so all we need to do is loop through the relational field and print links (as the only thing available in the content field: "destination ids"). I am sure there used to be this option in the docs but i cannot find it anymore eg:
{% set links = ez_field_value( footer, "first_links_row" ).destinationContentIds%}
{% for id in links %}
{{ render(controller("ez_content:viewAction", {"contentId": id, "template": "link.html.twig"})) }}
{% endfor %}
Where the link.html.twig would simple print the link:
<a href="{{ path( "ez_urlalias", {"contentId": id} ) }}">
{{ ez_field_value( content, "name" ) }}
</a>
If using a custom tpl is not possible with the render (controller ( helper then a new custom view type would also fix this issue, but i cannot find documentation for either.
You can create a twig function that would do that. We have something like this:
Definition:
new Twig_SimpleFunction(
'content_name',
array($this, 'getContentName')
),
Implementation:
public function getContentName($content, $forcedLanguage = null)
{
if (!$content instanceof Content && !$content instanceof ContentInfo) {
$contentInfo = $this->repository->getContentService()->loadContentInfo($content);
} elseif ($content instanceof Content) {
$contentInfo = $content->contentInfo;
} else {
$contentInfo = $content;
}
return $this->translationHelper->getTranslatedContentNameByContentInfo($contentInfo, $forcedLanguage);
}
which enables you to provide either content id, content info or content itself, and it returns translated content name

Blade helper, get variable from view without parameter

maybe someone know, how can I get variable with name "foo" from blade template get to static function which is used in this template.
For example I have:
<div class="collumns large-8">
{{ Helpers::setLetters('variable_name') }}
</div>
<div class="collumns large-8">
{{ $variable_name }}
</div>
Both divs should set same string because in setLetters function will be
return ${$name};
But, that should be instead $name, because in case about, will be error.
I use laravel 4.1
This doesn't go in your View, it should be in your controller.
Controller
$name = Helpers::setLetters('variable_name');
return \View::make('yourview', array( 'variable_name' => $name);

Laravel 4: Using flexible layouts within routes

I have an application without controllers and read about controller layouts in laravel 4 documentation and this other article too, but I don't know where to start for implement it within routes (version 4), how can I do that?
Error received: InvalidArgumentException, View [master] not found.
app/routes.php
<?php
View::name('layouts.master', 'layout');
$layout = View::of('layout');
Route::get('users/create', array('as' => 'users.create', function() use($layout) {
//#TODO: load view using 'layouts.master',
// desirable: append 'users.create' and 'users.menu' views to sidebar and content sections.
//return View::make('users.create');
return $layout->nest('content', 'master');
}));
?>
app/views/layouts/master.blade.php
<html>
<body>
#section('sidebar')
This is the master sidebar.
#show
<div class="container">
#yield('content')
</div>
</body>
</html>
app/views/users/create.blade.php
{{ Form::open() }}
{{ Form::text('name') }}
{{ Form::submit('submit') }}
{{ Form::close() }}
app/views/users/menu.blade.php
<!-- This is appended to the master sidebar -->
<p>Create user</p>
Update: I modified example code to clarify what I want to do. Check app/routes.php and its comments
The code in your routes file is trying to nest the master layout within itself, which isn't really what you want. You're getting the error because 'master' would look for app/views/master.blade.php. That's easily fixed by changing it to 'layouts.master', but I wouldn't like to think what might happen...
The root cause of the issue you're having is the difference between "yielding" views from a Blade template, and nesting them from a route. When you nest a route, you need to echo it rather than using the #yield tag.
// File: app/routes.php
View::name('layouts.master', 'layout');
$layout = View::of('layout');
Route::get('users/create', array('as' => 'users.create', function() use ($layout)
{
return $layout
->nest('content', 'users.create')
->nest('sidebar', 'users.menu');
}));
/*
|--------------------------------------------------------------------------
| View Composer
|--------------------------------------------------------------------------
|
| Code in this method will be applied to all views that use the master
| layout. We use that to our advantage by injecting an "empty" sidebar
| when none is set when returning the view. It will error otherwise.
|
*/
View::composer('layouts.master', function($view)
{
if (!array_key_exists('sidebar', $view->getData()))
{
$view->with('sidebar', '');
}
});
// File: app/views/layouts/master.blade.php
<html>
<body>
#section('sidebar')
This is the master sidebar
{{ $sidebar }}
#show
<div class="container">
{{ $content }}
</div>
</body>
</html>
Laravel's View composers are a powerful tool. If you have any data (eg logged-in user info) used by all views that share the same template(s), you can use the composers to save injecting the data every time you load the view.
You could also use the #parent tag to append content, assuming you;re using blade for templating. E.g. (in the view)
#section('sidebar')
#parent
<p>This is appended to the master sidebar.</p>
#stop
You don't need to use nesting views if you're using blade.
app/views/users/create.blade.php
You need to extend the master.blade
#extends('layouts.master')
#section('content')
// form stuff here
#stop
Now, all you need to do is call create.blade
return View::make('users.create')
Just throwing this out there as a possible solution using controller routing (whereas you can set the template from within the controller).
app/routes.php
Route::controller('something', 'SomethingController');
app/controllers/SomethingController.php
class SomethingController extends BaseController {
protected $layout = "templates.main"; // denotes views/templates/main.blade.php
public function getIndex() { // the "landing" page for "/something" or "/something/index"
$this->layout->content = View::make('something.index')->with("myVar", "Hello, world!"); // load in views/something/index.blade.php INTO main.blade.php
}
public function getTest() { // for "/something/test"
$this->layout->content = View::make('something.index')->nest("widget", "something.widget", array("myVar" => "Hello, World!"));
}
}
app/views/templates/main.blade.php
#include('templates.partials.header')
#yield('something')
#yield('content')
#include('templates.partials.footer')
app/views/something/widget.blade.php
I'm a widget. {{ $myVar }}
app/views/something/index.blade.php
#section('something')
I will go in the 'something' yield in main.blade.php
#stop
#section('content')
I will go in the 'content' yield in main.blade.php.
{{ $myVar }}
{{ $widget }}
#stop
?>
Now you can test http://myserver/something and http://myserver/something/test to see the differences. Note: not tested but as a rough example.

Categories