I have a navbar which is included in master.blade.php page. In my navbar I want to do something like
#if(count($cats)> 0)
#foreach($cats as $cat)
{{$cat->name}}
#endforeach
#endif
But I don't know how to get the controller used for every view.
Because navbar.blade.php is included after all. it doesn't use a route.
Controller name is CatsController and the function is cats.
I will probably need to get the list of categories using jquery or javascript. But I don't know how am I going to do that. Unfortuantely I forgat a lot about js
Laravel 5.4
Thanks for any help.
Use belows code in your navbar.blade.php. You dont have to use jquery or ajax, when you get data without controller
#php($cats = App\Cats::all())
#if(count($cats)> 0)
#foreach($cats as $cat)
{{$cat->name}}
#endforeach
#endif
Edit category model name, if its exist with another name name
I think you need to use javascript ajax
I am guessing you want to have data available to a layout without having to pass it from Controller to every view that extends that layout?
A View Composer would be the way to go if you have a layout that things are extending from and would like to pass data to that layout automatically.
Stackoverflow question similar in nature about needing data for header and footer of layout
View::composer('layouts.main', function ($view) {
$view->with('cats', Cat::all());
});
The layout will now have a $cats Collection to use.
Laravel 5.5 Docs - View Composers
Related
I am trying to assign *ngIf directive from angular code to the template during runtime. Not been able to figure out a way to do it. Is view/templateref an option to do it or is there a different way and an easier one. Is it possible in the first place?
Update:
The code is a little messy and jumbled, so avoided it. But here is the DOM code how it approximately looks and why I need to add inbuilt structural directives dynamically.
<div>
<input type="text" [value]="userProvidedValue">
<textarea [value]="someDynamicDOMCodefromWYSIWYG">
<!-- user provided provided code or dynamic code -->
</textarea>
</div>
<div>
<select *ngIf="fetchArraywithHttpFromuserProvidedValue">
<option *ngFor="let val of fetchArraywithHttpFrom-userProvidedValue" value=""></option>
</select>
</div>
<div>
<ng-template>
<!-- Some User provided code or dynamic code which might need to use *ngIf OR *ngFor -->
<!-- The *ngIf OR *ngFor will be added dynamically based on a manipulator function which is decided from the value of fetchArraywithHttpFromuserProvidedValue -->
</ng-template>
</div>
Update
I am doing a fetch request based on userProvidedValue value and the result of the fetch request decides the fetchArraywithHttpFromuserProvidedValue array. Second, based on the value of fetchArraywithHttpFromuserProvidedValue derived from fetch request the decision is made whether to show the user provided template or a predecided set of templates in switch option. (only part of user provided template needs the *ngIf directive. The user template is parsed in JS to get the needed part). The use case is similar to a tool that creates a HTML design/page which fetches structure from a user. This is exactly for a similar tool, just that I am not making a tool that creates a user defined HTML page.
Please help me out with this. If this is not possible, then please recommend an alternative that will allow me to assign functionality similarly or get me a workaround in this situation.
Update 2
Like pointed out in one of the answers below, all of the following templates failed to be added with proper parsing/compilation with elementref or using ViewContainerRef + TemplateRef:
<input [value]="someVariableFromClass"/>
<input value="{{someVariableFromClass}}"/>
<div *ngFor="let item of items">{{item}}</div>
The following works though, if the template is in the DOM before the application is being built and loaded (not dynamic addition):
<ng-template #tpl>
<!-- Add the template to #vcr using ViewContainerRef from the class -->
<div *ngFor="let item of items">{{item}}</div>
</ng-template>
<div #vcr>
<!-- Add the template from #tpl using ViewContainerRef from the class -->
</div>
Currently, I am trying out the compiler API in Angular and checking if compileModuleAndAllComponentsAsync<T>(moduleType: Type<T>): Promise<ModuleWithComponentFactories<T>> can help me in this use case. The issue seems like I will have a create a completely new component by assigning the html as a template to the component, then create a dynamic module, and then compile the whole before inserting into the view (Logic I am trying out currently - not working yet). After this (if I succeed), I will try adding the component template with a directive and see if that compiles right. Any help is welcome. It seems like I might end up by adding static directives to manual placeholders and adding [innerHTML]= / safeHTML / Sanitize API, if I dont succeed. Not ideal though. Please help with alternatives if you can.
I am using this example, though it's plunkr currently not working.
How can I use/create dynamic template to compile dynamic Component with Angular 2.0?
http://plnkr.co/edit/wh4VJG?p=preview
You don't call a fetch method inside an *ngIf. The ... inside *ngIf="..." gets executed every time angular decides to do change-detection and that might be dozens of times per second. You don't want to deploy a DDOS for your own backend.
This is why you should put a field like isUserProvidedValueValid there and update that field in the subscription of your HttpClient-call:
userProvidedValue: any;
isUserProvidedValueValid: boolean = false;
constructor(private httpClient: HttpClient) {}
doFetch() { // called by a button-click for example
this.isUserProvidedValueValid = false;
this.httpClient
.get<any>(SOME_URL)
.subscribe(res => {
if (res) { // you might have a complex check here, not just not-undefined
this.isUserProvidedValueValid = true;
}
// you might consider putting this in the if-clause and in the *ngIf only check for userProvidedValue being not null
this.userProvidedValue = res;
});
}
Now for the code that your user provides: first of all, you need to sanitize it. You can do it with a pipe inside a directive (you don't need to use ng-template, you use innerHtml of a normal tag for it) like in this example: https://stackoverflow.com/a/39858064/4125622
template: `<div [innerHtml]="html | safeHtml"></div>`,
Or before the .subscribe() in the code above, you can do
// domSanitizer needs to be injected in constructor as well
.map(res => this.domSanitizer.bypassSecurityTrustHtml(res));
If you need to transform this code, you can add another .map()-RXJS-mapper or another custom pipe - it's up to you which kind of transformer you prefer. In the transformer you can use VanillaJS for manipulation of the user-code. Perhaps an HTML-parser-plugin or a JSON-toHTML-parser-plugin or something similar might be useful to you - depends on the data type your user provides.
No you can't add structure directives dynamically, you need to approach it by thinking what is your app expecting later on.
For example, if you plan on looping through an array which I'm guessing is what you intend to do having looked at your code, you could do the following:
hotels: any;
<div *ngIf="hotels.length > 0">
<div *ngFor="let item of hotels">{{item.name}}</div>
</div>
I have 8 jade view that only one of them is loaded at the time and is filled by jquery into a div which has a controller.
Now, I have 2 question about these:
Does it necessary to define again the controller on top of my partial view(same controller with main controller) ?
All of these views has same ng-click. but after loading they doesn't work. However they work by jquery click event. Should I do any extra thing with them?
I had same problem with li element before, but I resolve it by getting help from ng-click not working from dynamically generated HTML by using compileData but I can't get result with button.
Code:
Main jade:
div(ng-controller="elementCtrl")
div#ddd(class="col-lg-7 col-md-5 col-sm-7")
Partial view sample:
div#spPartial()
div.col-lg-12.col-md-12.col-sm-12
span.col-lg-2.col-md-5.col-sm-5 Name
input#EnglishName(name="name" type="text" ng-model="elementModel.Name" value="#{Name}" class="col-lg-5 col-md-7 col-sm-5")
button(type="button" compile-Data name="btnSaveElement" ng-click="saveElement()") Save
Main part of controller:
//It loads the partial view - It works successfully
$http.post('/api/elements/getElementTypesPartial',
{
"ElementId": elementId,
"ProgramId": newVal,
"ElementTypeId": elementTypeId
})
.success(function (d2) {
$("#ddd").html(d2);
}
//It doesn't work at all
$scope.saveElement = function () {
alert();
alert($scope.elementId);
}
And one additional thing is that I put $scope.saveElement in root of controller scope. I don't have any idea about how angularJs manage $scope, So I see $scope.elementId in client code. Is it right or I should regenerate it($scope.saveElement) every time that partial is loaded?
Sorry I couldn't find any reference which describes these...
You should get rid of the jQuery loading and use an angular router which will load templates based on route configuration.
Since they are loaded by angular, it does all the compiling for you.
The router takes care of the ajax to get the templates automatically also.
Controllers also get defined in the routing config so you would be able to remove ng-controller from the templates
The change over shouldn't take long since setting up routing config is fairly easy to get it started
This would clear up the ng-click problems
I've recently asked a question on how to pass a variable in Smarty: Smarty - include template and update an existing variable
It's working fine for me, but now I need something a little more advanced from what I see.
In one template I attach a gallery slider template as a variable:
{$gallery_slider}
In the gallery template (which is a general file for other pages, so I don't want to change it) there's the jQuery slider with options. I would like to change the number of visible slides. For now it looks like this:
visible : {$partial.visible|default:5},
If I change default to 3 in the template, it works, but I would like to do this from the level of the template that calls the gallery - above {$gallery_slider}.
How do I do that? I've tried:
{assign var="partial.visible" value="3"}
and
{assign var="partial.visible|default:3"}
and some other combinations, none of them works.
I'd appreciate some suggestions.
I don't know how you used this as variable (probably fetch method) but you should rather use include in this case:
{include file="gallery.tpl" items=5}
{include file="gallery.tpl" items=3}
and now if in gallery.tpl you have:
Here I can display {$items} in my gallery<br />
output will be:
Here I can display 5 in my gallery
Here I can display 3 in my gallery
so you can use this variable and in loop (or other control structure) use this variable without any problem
I am currently working on a web application that uses jquery 1.9.1 and jquery mobile 1.3.2 in visual studio(MVC4 template).I have many pages where i use a side panel.The side panel has almost same elements in it, so i decided to put it in a partial view,but the elements in the side panel are not exactly same in all the pages.
so i am thinking to put all the elements of side panel used in all the pages in a partial view and selectively render them according to the page, i am using.
so is there any way by which i can render only selective elements from a partial view?
Do you really need to do this using Javascript?.
Lets organize the ideas:
I have many pages where i use a side panel
What I would do here is to create a layout page that you could use on all the views where you require to add this side panel. So the views you want to render this layout on the final html output should include the following section:
#{
ViewBag.Title = "Roles";
Layout = "~/Views/Shared/_SidePanelLayout.cshtml";
}
so i am thinking to put all the elements of side panel used in all the pages in a partial view and selectively render
Ok I would do the same, however, the rendering of the options, I would not use javascript. I would prefer to send the html of the only required options by sending the models to the view. This is the process I would code:
1-Whenever you request a page that uses this side panel layout, you should fill a ViewBag property (or a model) to pass the page name. So lets say that you have your Home/Index view uses this layout, you can do something like this:
public ActionResult Index()
{
ViewBag.PageName = "Home-Index"; //you could use constants or enums as best practice
return View();
}
At some point on your _SidePanelLayout view, I would place a Render Action call. This render action will in fact, render the side panel view with the specific options for that page:
#{ Html.RenderAction("GetOptions", "SidePanelController", ViewBag.PageName); }
This means that you will require a SidePanelController class with the method that will return your SidePanelView (with the specific options for your the page that you requested):
public class SidePanelController: Controller
{
public ActionResult GetOptions(string pageName)
{
//you may want to change this List<string> for a list of objects that include
//the properties you need like url, name, tooltip, etc
List<string> menuOptions = new List<string>();
//Determine which options should be rendered
/* your code */
//return the view with the filtered options
return PartialView("_SidePanelView", menuOptions);
}
}
That way you would have your requirements fullfilled. It's a bit more complex than using javascript, but it's more robust solution.
Hope this helps.
I'm trying to figure out what the best practice is for using jQuery in an MVC app. Specifically, I would like to know what I should do so that I don't clutter all my views with individual document.ready statements.
As an example:
I have the following Views:
/Views/Shared/_Layout.cshtml
/Views/Home/Index.cshtml
/Views/Home/_Dialog.cshtml
/Views/Home/_AnotherDialog.cshtml
I have a controller action that will render the Home/Index View, which uses the Layout and renders two partial views (or editor templates, display templates, etc.). This one controller action has rendered 4 or more views. Each view is using some jquery document.ready code.
Currently, I have the code at the bottom of each view:
// In Index
<script type="text/javascript">
$(function() {
$('#tabs').tabs()
});
</script>
// In _Dialog
<script type="text/javascript">
$(function() {
$('#some-dialog').dialog( ... );
});
</script>
I know this isn't a very good practice because it is already getting unmanageable in my small project. What are some good practices to follow when I have tons of pages that all need some jQuery / javascript initialization code separated across dozens of views?
You could do something along the lines of what Telerik do with their javascript registrar. Basically, make this registrar available in your view model. At the simplest level, all it has to do is keep track of strings added to it:
public class JavascriptRegistrar
{
private StringBuilder jsBuilder_ = new StringBuilder();
public Add(string js)
{
builder.Append(js).Append('\n');
}
public string ToString()
{
return "<script type=\"text/javascript\">" + jsBuilder_.ToString() + "\n</script>";
}
}
Your partial views will then add to this when rendering:
<h1>In my view!</h1>
#Model.Registrar.Add("$function() { /* ... */ }")
Finally, at the bottom of your main view, when you're done:
#Model.Registrar.ToString()
Which will write out all the javascript it has collected during rendering.
If the initialisation is specific to a view and you know it definitely won't be used outside that view, for example some page specific behaviour, then just leave it in the view!
There is nothing wrong with having script tags in all your views, as long as you aren't replicating js between views. I think people tend to misunderstand 'separation of concerns' in this case and think that simply means 'keep different languages away from each other at all costs'...that is wrong, clearly if some page initialisation logic/behaviour is specific to a page, then the html and js intrinsically 'concern' each other, therefore moving the js into a separate file is not really 'good practice', if anything it makes your code more difficult to understand.
I personally like to open up a View, and be able to see all the js and css that is specific to that page as soon as I open it, makes it nice and readable. However, obviously if code needs to be shared then you need to bust it out your view and get in your scripts folder whwere it can be referenced by anything!
EDIT
In your example above I see in your Index view you initialise your tabs. This is fine as it is, however, if you added tabs somewhere else in the project then it might be better to create your tabs using a .tabs class rather than #tabs id, and then in an external js file initialise all your tabs at once by calling $('.tabs').