Share data in every subview - view

I have created a layout which contains a header and the main content which changes regularly.
#include('tshop.includes.header')
#yield('content')
#include('tshop.includes.footer')
I have created the below view composer in order to pass the products in my basket to a pop up dialog in the header.
View::composer('tshop.includes.header', function($view)
{
$basket = App::make('BasketInterface');
$view->with( 'productsIterator' , $basket->getIterator() );
});
The thing is I want to share it in all views, including the main content.
I tried to use the share (and shares) function thinking that is the same as View::share but it isn't.
View::composer('tshop.includes.header', function($view)
{
$basket = App::make('BasketInterface');
$view->share( 'productsIterator' , $basket->getIterator() );
});
I also tried to use a view composer for the layout but in vain.
View::composer('tshop.layouts.default', function($view)
{
$basket = App::make('BasketInterface');
$view->shares( 'productsIterator' , $basket->getIterator() );
});
Next I placed the below filter to my constructor.
$this->beforeFilter(function()
{
$basket = App::make('BasketInterface');
View::share('productsIterator' , $basket->getIterator());
});
And it worked, but I use several controllers, so it's not the best thing to do. I know I can make a base controller class and extend it but isn't there a better way to do?

You may use App::before event to share some data to all the views globally using View::share, for example:
App::before(function($request) {
$basket = App::make('BasketInterface');
View::share( 'productsIterator' , $basket->getIterator() );
});
Now, you may access the $productsIterator from any view and btw, you have used shares instead of share. Also you may use a View composer instead of using View::share, like this:
View::composer('tshop.includes.header', function($view) {
$basket = App::make('BasketInterface');
return $view->with( 'productsIterator' , $basket->getIterator() );
});
In this case you need to use $view->with() method instead of share.

Related

Laravel Caching Issue General / with Components

I recently learned about caching in Laravel in a video series and wanted to apply it to my projects.
In this example project, I'm using a Livewire fullpage component (index) with 2 "modal" components each containing a "select" component which selects all records of a database table as a dropdown.
//Select Component Render Method
public function render()
{
$this->options = $this->modelName::orderBy($this->attribute, 'ASC')->get();
return view('components.input-field.select');
}
Select_Component_Controller_Example
Select_Frontend_Example
My problem here is that this component is called in both the create modal and the edit modal.
This causes a duplicate database query to be executed.
Double_Query_Executed_DebugBar
Unfortunately I am not quite clear how to apply the caching correctly now, in the example below you can see what I am trying to achieve. I would be very grateful for tips on the problem or even tutorial suggestions on the subject of caching, as I do not yet understand the application to this properly.
public function render()
{
$this->options = cache()->remember("options", 20, function() {
$this->modelName::orderBy($this->attribute, 'ASC')->get();
});
return view('components.input-field.select');
}
try_to_accomplish
With kind regards,
Daniel
You must return the results in callback
$this->options = cache()->remember("options", 20, function() {
return $this->modelName::orderBy($this->attribute, 'ASC')->get();
});

Is it ok to use App.__container__.lookup to access instances?

I need access to the ApplicationView from another view and I'm able to do so with App.__container__.lookup('view:application').
Is __container__ intended to be used this way?
Is there a better way to access instances of views?
(update)
My usecase:
My ApplicationView has a template with 2 columns.
The CSS is responsive so the size of the columns changes to accommodate the
width of the page.
I'm using Ember List View which requires height and width to be specified during initialization
I want to get the instance so I can access the DOM object to figure out its size
I can't use Ember.View.views because at that point, the ApplicationView has not been inserted into the DOM
Don't use that. One of the core developers said that whenever someone tries to use App.__container__, he would add another underscore.
If you really want to access an Ember.View intance use Ember.View.views['foo']. Where foo is the elementId of the view instance.
So if for example you want the App.ApplicationView instance:
App.ApplicationView = Ember.View.extend({
elementId: 'application'
});
// somewhere else in your code
var applicationViewInstance = Ember.View.views['application'];
Having said that, I never came across a situation where I needed to access view instances like that. If you can post your use case, I may be able to suggest alternative ways.
UPDATE: You want to access some properties of a view instance, from some other view instance (view height and width). You can pass those properties to the controller and let other controllers access them for using them in other views (source view -> source controller -> some other controller -> some other view):
App.ApplicationView = Ember.View.extend({
didInsertElement: function() {
var controller = this.get('controller'),
height = this.$().height(),
width = this.$().width();
controller.setProperties({
height: height,
width: width
});
}
});
App.SomeotherController = Ember.Controller.extend({
needs: ['application'],
applicationViewWidthBinding: 'controllers.application.width',
applicationViewHeightBinding: 'controllers.application.height'
});
App.SomeOtherView = Ember.View.extend({
// assuming its controller is an instance of App.SomeotherController
applicationViewWidthBinding: 'controller.applicationViewWidth',
applicationViewHeightBinding: 'controller.applicationViewHeight'
});

Wordpress Create Category AJAX Response

I currently have a plugin that allows a user to activate/deactivate categories to drive a menu. I've created an option for the toggle and have it functioning in the create form and edit form seamlessly. The only place I can't seem to add it is to the AJAX return from wordpress when the category is created. I can create the column when the Categories page is loaded but don't know how to tap into the AJAX Return without modifying the core. Is there a hook that I'm unaware of that allows you to modify this return?
Using Akmal's answer, this is my script to check if the Taxonomy-Category was created or not.
Thanks Akmal.
Wordpress version 3.8.2
$(document).ajaxComplete(function(event, xhr, settings) {
var queryStringArr = settings.data.split('&');
if( $.inArray('action=add-tag', queryStringArr) !== -1){
var xml = xhr.responseXML;
$response = $(xml).find('term_id').text();
if($response!=""){
console.log('This is the action.');
}
}
});
Do you try to run some Javascript after ajax return (after add new category)?
Try to put below code in your code when you create the custom field in category form :
$(document).ajaxComplete(function(event, xhr, settings) {
var queryStringArr = settings.data.split('&');
if ($.inArray('action=add-tag', queryStringArr) !== -1){
your_javascript_function(); //this is your js function
}
});

How can I assign a specific itemView to a certain model in a CompositeView collection?

I am using backbone.marionette and want to use different views for some Items from a collection passed to a CompositeView. Is this possible?
var vText = Backbone.Marionette.ItemView.extend({
template : "forms/form-element",
className : "control-group"
});
var vCheckbox = Backbone.Marionette.ItemView.extend({
template : "forms/form-element-checkbox",
className : "control-group"
});
var vForm = Backbone.Marionette.CompositeView.extend({
tagName : 'form',
template : 'forms/form',
className : 'crud-form form-horizontal',
itemView : // use different view for specific items based on collection modelData
})
I tried:
itemView : function(model) {
switch(model.get('inputType')) {
case "checkbox":
return vCheckbox;
break;
default:
return vText;
break;
}
}
But doesn't work. How can I achieve this?
this isn't directly supported right now, but wouldn't be too hard to add for your project's needs
https://github.com/derickbailey/backbone.marionette/blob/master/src/backbone.marionette.collectionview.js#L105-115
this is the function that retrieves the value of the itemView setting for a view. You could override it in your specific view:
Backbone.Marionette.CompositeView.extend({
// ...
getItemView: function(){
return this.itemView();
}
});
This seems like something that should be added to marionette directly, as well. Can you add an issue to the github issues list? https://github.com/derickbailey/backbone.marionette/issues link back to this SO post from the ticket.

backbone.js update vs add in view

I've got my models saving and updating using the regular save with a success callback.
But I'm trying to figure out how to define a separate add view depending on if the model is new, or an update to an already existing model.
This is not server side. I have the server create/update working fine, I'm trying to figure out what is the 'right' way to update the view.
My code is pretty straight forward
Myapp.FormInput = Backbone.Views.extend({
initialize: function(){...
},
submit_form: function(){
if(this.id===undefined){
// this is a new model, so create it
model.set(new Myapp.Model.set(Myapp.Models.Helpers.serialize_objects(form)));
model.set({parent_id:parent.id});
} else {
// this is an update to an existing model, so just update the model
model.set(Myapp.Model.set(Myapp.Models.Helpers.serialize_objects(form)));
model.url+='/'+this.id;
}
model.save(model,
{success: function(model){
Myapp.Collection.add(model);
}, error: function(){
alert('error creating or updating');
}}
});
});
What I like to do is initialize the 'View' from the router with a 'Model', if I am editing, and without a 'Model', if I am creating a new 'Model' from scratch.
The idea would be :
var Workspace = Backbone.Router.extend({
routes: { '/collection/:id' : 'edit_model',
'/collection/newObject' : 'new_model
},
new_model : function(){
myView = new A_View();
},
edit_model : function(){
myView = new A_View({model:aModel});
}
});
And then, in the 'render' method, check for a model in this view instance.
But.. this only works if your application use different routes for editing and creating models. Maybe you are doing everything in the same route in a most elaborate way (or you have other reasons).
You could try something like this:
Define your model.save 'success' function in the View (that is, in the same way that you define your submit_form in your example) and add a code line where you associate the model to this view:
successSaving : function( model ){
Myapp.Collection.add( model );
this.model = model; //here you save the model in your view.
}
In order this to work, you have to bind the view to your new success function (this is the reason you define it outside).
You could make it in the view initialize function like this (more information about '_bind' here):
_.bindAll(this, 'successSaving');
Now, in your 'render' method you can render the form and, after that, check if 'this.model' is 'undefined', if it is not, you know now that you have to fill the content.
Disclaimer: I have not checked the code, so probably a copy paste is not going to work but hopefully you can get the idea.

Resources