Bind custom attributes on Ember view with controller data in xhandlebars script - view

{{#each App.SampleViewController}}
{{#view App.SampleView contentBinding="this" sort-date="content.sortDate" name="content.name"}}
<a href="#" onclick="App.loadSampleDetails(this);" {{bindAttr id="content.id"}}>
{{/view}}
{{/each}}
How to add custom attributes/generic attributes (like in the above example sort-date/name attributes) to the view element from the xhandlebars script tag, I know that using attributeBindings we can add, but I have the dynamic data coming from controller through each.

You can use the attributeBindings property to define additional attributes that will get added to the DOM output for a view. See the "HTML Attributes" section in the Ember.View docs: http://docs.emberjs.com/#doc=Ember.View&src=false

Related

Calling messages.properties dynamically with controller model variable and Thymeleaf

I have my messages.properties like this:
tablas.menu.paises=Pa\u00EDses
tablas.menu.regiones=Regiones
tablas.menu.anhos=A\u00F1os
tablas.menu.universidades=Universidades
tablas.menu.usuarios=Usuarios
In the .html I have a menu showing each item with th:each:
<li class="nav-item" th:each="menu : ${menus}">
<a th:text="#{tablas.menu.${menu.nombre}}"></a>
</li>
For each "menu in ${menus}", menu.nombre has the values paises, regiones, anhos...
But thymeleaf doesn't recognise the model variable inside the #{}, and this it is giving me in the view the error when it doesn't find the message:
??tablas.menu.${menu.nombre}_es_ES??
Configuration is ok, if I change the call for #{tablas.menu.regiones} I get 'regiones' and so.
Is there any way to call a message from messages.properties dynamically using a model variable like this?
Thanks.
You can use the #messages utility object for this:
<a th:text="${#messages.msg('tablas.menu.' + menu.nombre)}" />
Or you can create the string using literal substitution:
<a th:text="#{|tablas.menu.${menu.nombre}|}" />
I would recommend using preprocessing only as a last resort, as bad values can cause runtime errors. (Although they do work for this.)

How to prevent loops in laravel global variable

I've created file GlobalVariable.php inside app\Composers
public function compose($view)
{
$categories = \App\Models\Category::all();
$view->with('globCategory', $categories);
}
then register to AppServiceProvider the code view()->composer('*', GlobalVariable::class);
I use global $globCategory for creating dynamic navbar
<ul class="nav nav-tabs border-0 flex-column flex-lg-row">
#foreach ($globCategory as $item)
<li class="nav-item">
{{$item->name}}
</li>
#endforeach
</ul>
the only problem here when I see laravel debuggar it show repetition of categories query.
here is the result
How to avoid this looping query? is there correct way?
The way you're registering your view composer (using '*' instead of a particular view name), it's going to call the compose method for every single rendered view + subview.
What you can do is instead of this:
view()->composer('*', GlobalVariable::class);
Have this:
\View::share('globCategory', \App\Models\Category::all());
This will globally share your categories (within views), and run the query only once.
View composers, as described from the laravel documentation, bind data to a view every time it is rendered. They clean our code by getting fetching data once and passing it to the view.
While it is possible to get the data in every controller method and pass it to the single view, this approach may be undesirable.
Replace the view name with an asterisk wildcard.

Set visibility of form input in thymleaf using th:if

I am new to thymeleaf and I have this problem.
I have a form to add and edit products.
From the controller I set request mapping to access this form view using
#RequestMapping("/products/add")
and
#RequestMapping("/products/edit/{id}")
I have a field in products ,Date endPromotion.
I want this input block that has endPromotion field to be shown only in edit mode.
How can I do that using thymleaf condition?
i tried somthing like
<div th:if="${|/products/{action}(action='edit')|}"> .. valid html code ... </div>
but it doesn't work
This should do the trick
<div th:if="${#strings.contains(#httpServletRequest.requestURI, '/products/edit/')}">
some content
</div>

Understanding Ember Views

I'm looking for some clarification on views in Ember.js
Coming from a rails background and I'm trying to ignore any preconceptions. From what I understand of the ember framework there are 5 components:
Routes: This is where we define the state of the application. The state is reflected in the URL. We can also define data loading here. Route classes are defined and on startup ember creates route objects which last for the duration of the application.
Models: This is where object data is defined. Can also define computed properties. A model object is created for each json object returned from the server.
Controllers: This mediates interactions between the models and templates/views. Controller classes are defined and on startup ember creates controller objects which last for the duration of the application. There is only ever a single instance of each controller class.
Templates: These describe the generated markup.
Views: These are specific templates or dom elements relating to a model. These are used to define interface events and send them to the controller for handling. Not sure when to create these.
As an example lets say I have a EventsController that has data loaded on the applicationRoute:
ScheduleApp.EventsController = Ember.ArrayController.extend();
ScheduleApp.ApplicationRoute = Ember.Route.extend({
setupController: function() {
this.controllerFor('events').set('content', ScheduleApp.Event.find());
}
});
Now in my template instead of iterating over each and displaying the information I want to iterate over each and create an associated view so I can add interactions to each event. I presume I would need to create a new view for each event and have it display in my template. However, I'm not sure where I create these views. Do I define a view class and then ember will create a new view object each time I call it using the view helper? Eventually I would like to use the appendTo on the view to inject my events to different places in the dom. Where would this be defined?
I've tried reading over the ember.js guide for views but it describes the context of a creating a single view. I think I want to make many views for each event and then dynamically interact with those objects.
Up to now ember has been outrageously clever so I would assume there is a built in method for generating these views. After all, most user interfaces are full of lists that require interactions. The problem is the list I'm trying to make I then want to spread over the dom depending on its attributes.
As per your code, App.EventsController has a list of events, now let us say we want the UI to have a list of events displayed and for each event say we want the view to have a delete button which deletes the event when the user clicks
One way to accomplish is by using Ember.CollectionView, the collection view as the name suggests is tailored for these sort of requirements, in many Ember examples the usage of view is not defined because ember auto-generates it for you but in some cases we might need to explicitly define a view to meed our requirements
App.EventsView = Ember.CollectionView.extend({
// It needs a list of data to iterate upon
// We are binding it to the controllers content data which
// is a list of events
contentBinding: "controller.content",
appendSpan: function(){
view = Ember.View.create({tagName: 'span'});
this.get("childViews").forEach(function(child){
view.appendTo(child);
});
},
// Now we need to also define a view template that will be
// generated for all the elements in the content array
// This could in turn be another collection view if required
// I am going to keep it simple for now
itemViewClass: Ember.View.extend({
templateName: "event",
deleteEvent: function(){
// Implement Delete
this.get("content").deleteRecord();
},
notifyUser: function(){
// The record doesn't get deleted as soon as user clicks, the request goes to
// server and server deletes the record and sends back the response to the
// client, Hence I'm using an observer here on isDeleted property of the record
if(this.get('content.isDeleted')){
alert("Record deleted Successfully");
}
}.observes('content.isDeleted')
})
})
Important Note Inside the CollectionView definition this.get("content") refers to the array of events, while in itemViewClass this.get("content") refers to the single event object
//Defining the template
//Assuming the event model has a name property
<script type="text/x-handlebars" data-template-name="event">
Name: {{view.content.name}}
<a {{action deleteEvent target="view"}} href="#">Delete Event</a>
</script>
Now when you hit your application_url/events
you'll a list of events each event has a delete button, I hope this clears some concepts
For more information about CollectionView
Update as per the comment:
If you want to append another view to each child view, you can do so by editing the template of itemViewClass as follows
<script type="text/x-handlebars" data-template-name="event">
Name: {{view.content.name}}
<a {{action deleteEvent target="view"}} href="#">Delete Event</a>
{{ view App.SomeOtherView }}
</script>
it can be a partial too as follows
<script type="text/x-handlebars" data-template-name="event">
Name: {{view.content.name}}
<a {{action deleteEvent target="view"}} href="#">Delete Event</a>
{{ partial "somePartial" }}
</script>
or if you want to do it programmatically say, you click a button in the EventsView template and on click all the childs view must have a span tag appended to it(I am very bad at giving examples)
//This is the template for App.EventsController,
//template-name = "events" => view is App.EventsView and controller App.EventsController
<script type="text/x-handlebars" data-template-name="events">
<a {{action appendSpan target="view"}} href="#"> Append </a>
</script>
appendSpan is defined in the CollectionView

MVC3 _Layout.cshtml...disableing/enabling menu items

I have an MVC3 C#.Net project. When I initially load my Web site, I want to route to an Index page and have the navigation tabs at the top of the screen be disabled until a selection is made. Once a selection is made, the site routes to a details page. I would then like to enable the navigation menu itmes. How can I do this? Pass a ViewBag around? Not sure
I think the problem is that Index page doesn't follow a layout of the rest of the website, therefore index page shouldn't use a master layout.
On your index page:
#{
ViewBag.Title = "Index page";
// Null or a custom layout
Layout = null;
}
<p>Your content below</p>
If you want to render a menu on some condition, then store menu in a partial view model, e.g. SiteNavigation.cshtml
You can then render this view based on some condition. E.g.
#if(true){
#{ Html.RenderPartial("SiteNavigation"); }
}
I found an answer to my question. #CodeRush's answer is cool, which I will use in another scenario. But I like the implementation, below, for my prticular situation. In the Object1Controller Index get Action, I added the below code:
ViewBag.Hidden = "hidden";
Then in the Details get Action, which is the Action called when a link is clicked on the Index view, I added this code:
ViewBag.Hidden = "visible";
Then in the _Layout.cshtml I added this code:
<li style="visibility: #ViewBag.Hidden">#Html.ActionLink("About", "About", "Home")</li>
Which renders as:
<li style="visibility: hidden">About</li>
or
<li style="visibility: visible">About</li>
In the other Controllers, I don't need to set the ViewBag.Hidden property since the default for the visibility attribute is "visible". For the other Controllers, the ViewSource shows:
<li style="visibility: ">About</li>
Which renders as visible

Resources