Set All Variables in View

Set all variables in view

The code you presented in your question has some issues and it is not immediately reproducible; let me exemplify:

  • You have two different variables, IsShowing and isShowing: is that a typo, or they are supposed to be different? IsShowing completely hides the list. I will assume that they have different purposes.
  • It is better to follow the convention in Swift: all variable start lower cased, so avoid IsShowing or StaffList as variable names.
  • The list in the code above is not visible anyhow because, when you have more than one view in the body, you need to embed them in a container, like a VStack.
  • onChange(of:perform:) takes one parameter in the closure, the code above does not compile - watch out, because SwiftUI throws errors that are misleading in this case.
  • You want to change all toggles in ToggledView: the variable toggled could be used for that purpose, but I will assume that it has a local scope, so I added a Toggle in my example below.

Coming to the solution: you need to bind the variable in the parent view with another variable in the child view, then listen to changes in the child variable.

The parent view has an @State variable, it needs to be passed to a @Binding variable in the child view. You listen to the changes with .onChange(of:) { }.

In the code below, each item in the list has their own specific toggle, but when you change the one on the top of the view, all of them will change accordingly.

Parent view:

struct ContentView: View {
let isShowingList = true // This replaces the "IsShowing" variable in the question

@State var isShowing = false

var body: some View {

// Embed content in a container, like VStack
VStack {

Toggle("Toggle all items", isOn: $isShowing)
.padding()

Spacer()

if isShowingList {
ForEach(staffList, id: \.self) { item in

// Pass the variable from this view to the child view
ToggledView(globalToggle: $isShowing)
}
}

Spacer()
}
.padding()
}
}

Child view:

struct ToggledView: View {

// Make state variables private
@State private var toggled = false

// This is where the magic happens: changing iShowing in the parent view
// will change globalToggle in this view
@Binding var globalToggle: Bool

var body: some View {
Toggle(toggled ? "True" : "False", isOn: $toggled)

// .onChange(of:) closure receives one parameter: the variable changed
.onChange(of: globalToggle) { value in
toggled = value
}
}
}

List all registered variables inside a Laravel view

Use the dd helper:

{{ dd(get_defined_vars()) }}

Read more: https://laravel.com/docs/5.4/helpers#method-dd

Update (thx, @JoeCoder): you can further cutdown on the "useless" variables by doing:

{{ dd(get_defined_vars()['__data']) }}

How to pass data to all views in Laravel 5?

This target can achieve through different method,

1. Using BaseController

The way I like to set things up, I make a BaseController class that extends Laravel’s own Controller, and set up various global things there. All other controllers then extend from BaseController rather than Laravel’s Controller.

class BaseController extends Controller
{
public function __construct()
{
//its just a dummy data object.
$user = User::all();

// Sharing is caring
View::share('user', $user);
}
}

2. Using Filter

If you know for a fact that you want something set up for views on every request throughout the entire application, you can also do it via a filter that runs before the request — this is how I deal with the User object in Laravel.

App::before(function($request)
{
// Set up global user object for views
View::share('user', User::all());
});

OR

You can define your own filter

Route::filter('user-filter', function() {
View::share('user', User::all());
});

and call it through simple filter calling.

Update According to Version 5.*

3. Using Middleware

Using the View::share with middleware

Route::group(['middleware' => 'SomeMiddleware'], function(){
// routes
});

class SomeMiddleware {
public function handle($request)
{
\View::share('user', auth()->user());
}
}

4. Using View Composer

View Composer also help to bind specific data to view in different ways. You can directly bind variable to specific view or to all views. For Example you can create your own directory to store your view composer file according to requirement. and these view composer file through Service provide interact with view.

View composer method can use different way, First example can look alike:

You could create an App\Http\ViewComposers directory.

Service Provider

namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ViewComposerServiceProvider extends ServiceProvider {
public function boot() {
view()->composer("ViewName","App\Http\ViewComposers\TestViewComposer");
}
}

After that, add this provider to config/app.php under "providers" section.

TestViewComposer

namespace App\Http\ViewComposers;

use Illuminate\Contracts\View\View;

class TestViewComposer {

public function compose(View $view) {
$view->with('ViewComposerTestVariable', "Calling with View Composer Provider");
}
}

ViewName.blade.php

Here you are... {{$ViewComposerTestVariable}}

This method could help for only specific View. But if you want trigger ViewComposer to all views, we have to apply this single change to ServiceProvider.

namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ViewComposerServiceProvider extends ServiceProvider {
public function boot() {
view()->composer('*',"App\Http\ViewComposers\TestViewComposer");
}
}

Reference

Laravel Documentation

For Further Clarification Laracast Episode

If still something unclear from my side, let me know.

Make variables available in the whole view (including @yields) using View composers

Use View::share() instead of with

class BaseComposer{
public function compose($view){

$data = array(
'user' => \Auth::user()
);

View::share($data);
}
}

Regarding your comment in dashboard.blade.php, you don't need the @extends if you always set the layout in your controller and it is best practice to only define the layout in one place.

How to share a variable across all views?

I usually use View Composers so it's more clear and readable.

For example If I want to share a variable with the main navbar to all of my views I follow the below rules:

1. Create new service provider

You can create a service provider with artisan cli:

php artisan make:provider ViewComposerServiceProvider

In the ViewComposerServiceProvider file create composeNavigation method in which has the blade template main.nav-menu that represents the navmenu with shared variables.

The ViewComposerServiceProvider looks like:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ViewComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
$this->composeNavigation();
}

/**
* Register the application services.
*
* @return void
*/
public function register()
{
//
}

private function composeNavigation()
{
view()->composer('main.nav-menu', 'App\Http\ViewComposers\NavComposer');
}
}

2. Create Composer

As you saw in the file above we have App\Http\ViewComposers\NavComposer.php so let's create that file. Create the folder ViewComposers in the App\Http and then inside create NavComposer.php file.

The NavComposer.php file:

<?php

namespace App\Http\ViewComposers;

use App\Repositories\NavMenuRepository;
use Illuminate\View\View;

class NavComposer
{
protected $menu;

public function __construct(NavMenuRepository $menu)
{
$this->menu = $menu;
}

public function compose(View $view)
{
$thing= $this->menu->thing();
$somethingElse = $this->menu->somethingElseForMyDatabase();

$view->with(compact('thing', 'somethingElse'));
}
}

3. Create repository

As you saw above in the NavComposer.php file we have repository. Usually, I create a repository in the App directory, so create Repositories directory in the App and then, create inside NavMenuRepository.php file.

This file is the heart of that design pattern. In that file we have to take the value of our variables that we want to share with all of our views.

Take a look at the file bellow:

<?php

namespace App\Repositories;

use App\Thing;
use DB;

class NavMenuRepository
{

public function thing()
{
$getVarForShareWithAllViews = Thing::where('name','something')->firstOrFail();
return $getVarForShareWithAllViews;
}

public function somethingElseForMyDatabase()
{
$getSomethingToMyViews = DB::table('table')->select('name', 'something')->get();

return $getSomethingToMyViews;
}

}

Laravel 5 - global Blade view variable available in all templates

Option 1:

You can use view::share() like so:

<?php namespace App\Http\Controllers;

use View;

//You can create a BaseController:

class BaseController extends Controller {

public $variable1 = "I am Data";

public function __construct() {

$variable2 = "I am Data 2";

View::share ( 'variable1', $this->variable1 );
View::share ( 'variable2', $variable2 );
View::share ( 'variable3', 'I am Data 3' );
View::share ( 'variable4', ['name'=>'Franky','address'=>'Mars'] );
}

}

class HomeController extends BaseController {

//if you have a constructor in other controllers you need call constructor of parent controller (i.e. BaseController) like so:

public function __construct(){
parent::__construct();
}

public function Index(){
//All variable will be available in views
return view('home');
}

}

Option 2:
Use a composer:

  1. Create a composer file at app\Composers\HomeComposer.php

NB: create app\Composers if it does not exists

<?php namespace App\Composers;

class HomeComposer
{

public function compose($view)
{
//Add your variables
$view->with('variable1', 'I am Data')
->with('variable2', 'I am Data 2');
}
}

Then you can attached the composer to any view by doing this

<?php namespace App\Http\Controllers;

use View;

class HomeController extends Controller{

public function __construct(){

View::composers([
'App\Composers\HomeComposer' => ['home'] //attaches HomeComposer to home.blade.php
]);

}

public function Index(){
return view('home');
}

}

Option 3:
Add Composer to a Service Provider, In Laravel 5 I prefer having my composer in App\Providers\ViewServiceProvider

  1. Create a composer file at app\Composers\HomeComposer.php

  2. Add HomeComposer to App\Providers\ViewServiceProvider

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use View;
use App\Composers\HomeComposer;
use Illuminate\Support\Facades\Blade;

class ViewServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}

/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//add to all views
view()->composer('*', HomeComposer::class);
//add to only home view
//view()->composer('home', HomeComposer::class);
}
}

Getting All Variables In Scope

No. "In scope" variables are determined by the "scope chain", which is not accessible programmatically.

For detail (quite a lot of it), check out the ECMAScript (JavaScript) specification. Here's a link to the official page where you can download the canonical spec (a PDF), and here's one to the official, linkable HTML version.

Update based on your comment to Camsoft

The variables in scope for your event function are determined by where you define your event function, not how they call it. But, you may find useful information about what's available to your function via this and arguments by doing something along the lines of what KennyTM pointed out (for (var propName in ____)) since that will tell you what's available on various objects provided to you (this and arguments; if you're not sure what arguments they give you, you can find out via the arguments variable that's implicitly defined for every function).

So in addition to whatever's in-scope because of where you define your function, you can find out what else is available by other means by doing:

var n, arg, name;
alert("typeof this = " + typeof this);
for (name in this) {
alert("this[" + name + "]=" + this[name]);
}
for (n = 0; n < arguments.length; ++n) {
arg = arguments[n];
alert("typeof arguments[" + n + "] = " + typeof arg);
for (name in arg) {
alert("arguments[" + n + "][" + name + "]=" + arg[name]);
}
}

(You can expand on that to get more useful information.)

Instead of that, though, I'd probably use a debugger like Chrome's dev tools (even if you don't normally use Chrome for development) or Firebug (even if you don't normally use Firefox for development), or Dragonfly on Opera, or "F12 Developer Tools" on IE. And read through whatever JavaScript files they provide you. And beat them over the head for proper docs. :-)

How do I initialize a class over the course of several view controllers

You can't initialize a class over time. You can set an instance's properties over time. That being the case, what you're doing seems fine.
However, alternatively you could keep calling into a builder that creates the Event fully formed only when all the needed info has been provided. Imagine an architecture like this (try it out in your playground):

class Event : CustomStringConvertible {
let fee : String
let fi : String
let fo : String
let fum : String
init(fee:String, fi:String, fo:String, fum:String) {
self.fee = fee; self.fi = fi; self.fo = fo; self.fum = fum
}
var description : String {
"Event: \(fee) \(fi) \(fo) \(fum)"
}
}

class EventBuilder {
private var fee : String?
private var fi : String?
private var fo : String?
private var fum : String?
private var event : Event?
private func makeEventIfPossible() {
guard event == nil else {return}
if let fee = fee,
let fi = fi,
let fo = fo,
let fum = fum {
print("making event")
self.event = Event(fee: fee, fi: fi, fo: fo, fum: fum)
}
}
func takeFee(_ fee:String) {
self.fee = fee
makeEventIfPossible()
}
func takeFi(_ fi:String) {
self.fi = fi
makeEventIfPossible()
}
func takeFo(_ fo:String) {
self.fo = fo
makeEventIfPossible()
}
func takeFum(_ fum:String) {
self.fum = fum
makeEventIfPossible()
}
func giveEvent() -> Event? {
self.event
}
}

let b = EventBuilder()
b.takeFee("Fee")
b.takeFi("Fi")
b.takeFo("Fo")
b.takeFum("Fum")
if let event = b.giveEvent() {
print(event) // and away we go
}

You can pass the EventBuilder around, different objects can call different take methods, and no one can get the Event with giveEvent until all the info has been supplied and the Event has been created. As you can see, the Event is created just once, and none of its properties are Optional. The builder hides the whole creation process behind a functional representation (hence the name).

I can imagine further refinements, like you could make the take methods throws methods where they would refuse to accept a value if that value had already been set, and so on. Also I think you might use keypaths somehow to make the code neater/smaller.

Pass more than one variable from controller to view in cakephp

The blog tutorial describes very well how to set data to the view. I recommend you to do the tutorial first, it gives you all you need to do your first steps.

You can set variables using $this->set() in your controller:

$this->set('first', 'second');
$this->set(array('foo' => 'bar', 'something' => 'else'));

The first will make the variable $first with the value second available in the view. The second will make $foo with value bar and $something with value else available in the view.

Controll::set() is setting the data to the view instances viewVars property. When the view is rendered it turns them into variables available in the view templates.

And do yourself and other people who look at your code a favour and follow the conventions and coding standards.



Related Topics



Leave a reply



Submit