Rhodes Rhomobile - Override the layout behavior for a particular view - layout

I need some help with a very specific case.
I would like to override the layout behavior for a particular view.
I did found the Rhodes documentation describing what to do.
(a copy of the Rhodes documentation is pasted at bottom of this text)
I tried to use the second alternative ("call the layout method on the controller to overwrite the default layout name") but it did not worked.
I assume I might have misunderstood how to code the controller or hopefully only have a syntax error...
See more information about the application below.
Could anyone please tell me how I should do it ?
What would be the right syntax ?
Or should I use another method ?
Thanks in advance.
Louis Deschenes
Here are some informations about the application and what I did:
Simple application
Build is for iPhone
Application start in "Calculator" view
"Calculator" view call "Control" view that call "Help" view
App structure:
app/
-> index.erb (Control view)
-> layout.erb (Standard layout)
-> calculatorlayout.erb (Customize layout for Calculator view)
-> calculator/
-----> index.erb (Calculator view)
-----> calculator_controller.erb (Controller to be able to override layout)
-> help/
-----> index.erb (Help view)
I created Calculator_controller.erb containning
require 'rho/rhocontroller'
require 'helpers/browser_helper'
class CalculatorController < Rho::RhoController
include BrowserHelper
layout :calculatorlayout (Thats what Rhodes doc mentionned to do)
As I said this does not work. Please tell me the right way to do it.
Note: As a temporily mesure I did a copy of app/calculatorlayout.erb into app/calculator/layout.erb
This does the rendering right when the app start in "Caculator" view,
but if I navigate to "About" view and back to "Calculator" view the rendering of the calculator is done with the standard layout.
--------Rhodes Documentation--------------------------------------------
If you would like to override or customize layout behavior, you can
call the render function with the following parameters:
render :action => 'index',
:layout => 'mycustomlayout', :use_layout_on_ajax => false
The first argument is the action you would like to render. Next is the
(optional) layout name, which assumes the application root as a base
directory. In the above example, Rhodes would look for a file called
“mycustomlayout.erb” in the application root directory (you also may
use :layout => false to disable the use of a layout template). The
use_layout_on_ajax argument tells Rhodes whether or not to use the
layout on Ajax calls (default is false).
You can call the layout method on the controller to overwrite the
default layout name:
layout :mycustomlayout
This will force the render call to use mycustomlayout.erb in place of
the default layout file for all actions of this controller.

In the controller, you need to specify an action method. The render method of an action is what handles the layout property. You cannot simply designate a layout for an entire controller. Below is an example controller file. You would then need an index.erb view file to correspond to the index action method.
CalculatorController.rb
require 'rho/rhocontroller'
require 'helpers/browser_helper'
class CalculatorController < Rho::RhoController
include BrowserHelper
def index
# perform any logic or fetch objects for the index.erb view
render :action => :index, :layout => 'calculatorLayout'
end
end

Unfortunately Rhodes has godawful documentation so its mechanics can be difficult to decipher. But I must mention that unfortunately Geoffrey is entirely wrong in this point:
You cannot simply designate a layout for an entire controller
Actually, you can simply designate a layout for a controller. There are tons of ways, but specifically you can do as the docs supposedly mention, just not in the way 'ideschenes' tried. If you inspect the source code in render.rb you would notice that RhoController defines a setter method for this exact purpose, which is a basic Ruby mechanic.
def self.layout(name)
#layout = name
end
Therefore you can either use self.layout = :layout_name or #layout = :layout_name inside the controller to define a default layout. I don't know the complexities of how it may be overridden, but this technique will allow you to set a default layout for any controller. I tested it myself.
There is also a method in RhoController which retrieves the layout name, and you can of course override this inside your own controller if you want to customize the behavior for choosing a layout.
def self.get_layout_name
#layout.nil? ? 'layout' : #layout
end

Related

What exactly does layout_scrollFlags = "snapMargins" do?

I've read the documentation of this attribute:
An additional flag to be used with 'snap'. If set, the view will be snapped to its top and bottom margins, as opposed to the edges of the view itself.
https://developer.android.com/reference/com/google/android/material/appbar/AppBarLayout.LayoutParams.html#scroll_flag_snap
But I can't observe any actual effect in my app. What margin are they talking about? Every margin on the CollapsingToolbarLayout (on which this attribute is set) completely destroys the layout.
Not sure if it's useful yet, but here is the difference:)
If you pass snap as scroll flag, then it will move your view (in my case this search bar, it's linearLayout) to it's edge NOT INCLUDING the margin_layout
Then I've tried snap|snapMargin and it moved with the margin
P.S. No idea why snapMargin doesn't work without snap ¯\_(ツ)_/¯
This attribute is responsible for a scrolling behavior of AppBarLayout and its children. You can apply it directly to AppBarLayout or on the inside views, in the xml layout of your AppCompatActivity. It has to be an instance of AppCompatActivity if you want to use AppBar features. Also, the design library must be included in Gradle dependencies, like so: implementation 'com.android.support:design:26.1.0'
Please refer this link:-[https://medium.com/#tonia.tkachuk/appbarlayout-scroll-behavior-with-layout-scrollflags-2eec41b4366b][1]

How to display data from a model from a Yii 1.1 layout file?

I'd like to have the layout reflect some data from a model. However, the render method from the CController class passes the structured data only to the view file, while the layout file only gets the rendered view passed.
So, how to best have the layout display data from a model?
Two possibilities come to mind:
Make Yii's layout file a no-op, mimicking layout logic manually from the view.
Override CController's render method in its subclass.
I'm not so happy with either variant, so maybe someone has a cleaner idea on how to do it?
Another way is to define a public variable in your controller class, something like:
class MyController extends Controller {
public $test = 'foo';
....
That value can then be accessed within a layout:
echo $this->test;
And manipulated in an action:
public function actionMyaction(){
$this->test = "bar";
...
Obviously it's not ideal if you have many variables that you need to use in a layout. One solution is to use an array of parameters. Alternatively you could look at making your layout more minimal and using CWidget to create reusable components for use inside your views.
For example, you obviously wouldn't want to have the code for your main navigation duplicated inside every view, so the obvious solution is to have in the layout, but if it becomes inconvenient to handle the data you could have an instance of a widget that renders out the navigation inside each view (and you can pass data to the CWidget class) something like:
$this->widget("MainNavigation",array("params"=>$params));

Yii is not rendering theme

I'm having a strange issue with Yii and a theme. I set it in config/main.php like:
'theme'=>'themeName',
as usual. But when I try to render a view, it is rendered as is, without any layout, as if I called:
$this->renderPartial
I double check that I don't call for renderPartial, the themes seem to be equal to all the others theme I've done. What can be this issue about?
Thank's for any help, I'm going out of mind on this...
Here is the structure and syntax that you should have to check
-yiiroot
-!-!protected
-!-!-!controllers
-!-!-!-!TestController.php
-!-!themes
-!-!-!themeName (it was the one that you have set on config file)
-!-!-!-!views
-!-!-!-!-!layouts
-!-!-!-!-!-!main.php // It would be default what if public $layout has not been overwriten or the layout file which has been set was not found
-!-!-!-!-!test
-!-!-!-!-!-!viewName.php
On controller TestController
public $layout is main as default or is overwritten there
in actionIndex you set $this->render('viewName');
If you rendered your page by method renderPartial() directly in controller, you would not get the layout template for sure
render() is commonly used to render a view that corresponds to what a
user sees as a "page" in your application. It first renders the view
you have specified and then renders the layout for the current
controller action (if applicable), placing the result of the first
render into the layout. It then performs output processing (which at
this time means automatically inserting any necessary tags
and updating dynamic content) and finally outputs the result.
renderPartial() is commonly used to render a "piece" of a page. The
main difference from render() is that this method does not place the
results of the render in a layout. By default it also does not perform
output processing, but you can override this behavior using the
$processOutput parameter.
renderFile() is a low-level method that does the grunt work of
rendering: it extracts the data variables in the current scope and
then runs the view code. The other two methods internally call this
one, but you should practically never need to call it yourself. If you
do, keep in mind that you need to pass in a file path (not a view
path).
Reference: Yii difference between rendering functions

Global sidebar with widget support

I would like to make a layout with a sidebar that can have widgets from different modules. Lets say there shall always be a login widget at the top if the user isn't logged in then it shall show user info. The getting started album guide could use it to display the latest albums and so on, i hope you understand how i want to use the sidebar.
Could it be done with a config file in autoload and a small code that read that config and calls the widgets on every page load?
There are several ways of page composition in Zend Framework 2:
1. Switching between Layouts
By default, ZF2 provides you with a single layout template layout.phtml.
In real-life applications, you will probably need to have several layouts
and switch the layout for certain controller/action. In each of your layouts, you will be able to show different widgets/sidebars.
2. Partial Views
A partial view is a .phtml view template file which can be rendered by another
view template. Partial views allow to compose your page of pieces and reuse pieces
of view rendering logic across different view templates. This is accomplished through the Partial view helper.
3. Placeholder View Helper
The Placeholder is another useful view helper allowing for capturing HTML
content and storing it for later use. Thus, analogous to the Partial
view helper, it allows to compose your page of several pieces.
4. Forward Controller Plugin
With the Forward controller plugin, you are able to call an action (for example, the action rendering some widget) from another module/controller from your controller and grab the output of that action. Then you are able to incorporate that output into your page.
5. Use View Models for Page Composition
When you write action methods for the controller classes, you use the ViewModel
class as a variable container for passing the variables from controller to view template,
and for overriding the default view template name. But, actually the ViewModel class is more than just a variable container plus view template name. In fact, it is closely related to the layout and page composition.
The third big capability of the view model class is that it allows for combining several
view models in a tree-like structure. Each view model in the tree has the associated
view template name and data variables that can be passed to the view template to control
the process of rendering.
This feature is internally used by Zend Framework 2 when "combining" the layout view template and the view template associated with the controller's action method. ZF2 internally creates the view model for the layout template and assigns it with layout/layout view template name. When your controller's action method returns the ViewModel object, this object is attached as a child to the layout view model.
So, you can attach your own view models to the default view model to render the page of pieces that you want.

MVC basics: Should I add a UIViewController, a Delegate or a Source to my custom view?

my question is about view controllers, delegates and all that in general. I feel perfectly comfortable with UIView, UIViewController, Delegates and Sources, like UITableView does for instance. It all makes sense.
Now I have implemented my first real custom view. No XIBs involved. It is an autocomplete address picker very much like in the Mail application. It creates those blue buttons whenever a recipient is added and has all the keyboard support like the original.
It subclasses UIView. There is no controller, no delegate, no source. I wonder if I should have either one of those? Or all, to make it a clean implementation.
I just cannot put my finger on the sense a view controller would make in my case. My custom view acts much like a control and a UIButton doesn't have a controller either.
What would it control in my view's case?
Some of my thoughts:
For the source: currently the view has a property "PossibleAutocompleteRecipients" which contains the addresses it autocompletes. I guess this would be a candidate for a "source" implementation. But is that really worth it? I would rather pass the controller to the view and put the property into the controller.
The selected recipients can be retrieved using a "SelectedRecipients" property. But views should not store values, I learned. Where would that go? Into the controller?
What about all the properties like "AllowSelectionFromAddressBook"? Again, if I compare with UIButton, these properties are similar to the button's "Secure" property. So they are allowed to be in the view.
The delegate could have methods like "WillAddRecipient", "WillRemoveRecipient" and so on and the user could return TRUE/FALSE to prevent the action from happening. Correct?
Should I maybe inherit from UIControl in the first place and not from UIView?
And last but not least: my custom view rotates perfectly if the device is rotated. Why don't all views? Why do some need a controller which implements ShouldAutoRotateToDeviceOrientation()?
Does it make sense what I wrote above? In the end I will provide the source on my website because it took me some time to implement it and I would like to share it as I have not found a similar implementaion of the Mail-App-like autocomplete control in MonoTouch.
I just want to learn and understand as much as possible and include it in the source.
René
I can answer part of your question.
I just cannot put my finger on the
sense a view controller would make in
my case
The ViewController is responsible for handling the View's state transitions (load, appear, rotate, etc) These transitions are used mainly when you use a navigation component (UINavigationViewController, UITabBarController). These components needs to received a ViewController that will handles the view's transitions.
For exemple, when you push a ViewController on a UINavigationViewController, it will cause the ViewDidLoad, ViewWillAppear, ViewDidAppear. It will also cause the ViewWillDisappear, ViewDidDisappear of the current ViewController.
So, if your application has only one portrait view, you don't need a ViewController. You can add your custom view as a subview of the main window.

Resources