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.
Related
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
Alright, I really need some help here because I am driving myself crazy. I have a messaging app that I want to add about 300+ emoticons/pics for that are located in the res folder. The files format of them are "thumbs_00001.png, thumbs_00002.png, thumbs_00003.png, etc...).
I have a dialog that opens up and displays a small menu for the user to select which image they want with:
final Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.emoticons);
dialog.setTitle("Emoticons");
dialog.show();
I usually would hardcode all of the ImageButtons, however 300+ images would take me quite a long time and I figure that it can be done dynamically (at least I hope so). The problem is that I don't know how to do this, which is why I am asking it here.
I need to figure out how to populate a layout file with all of the images (i.e. thumbs_00001.png to thumbs_00080.png, thumbs_00081.png to thumbs_00103.png, etc...), then also have an onclick listener for each. Thank you for any and all help.
Use a GridView or ListView. Then make an Adapter and call ListView.setAdapter() to show your image list.
If you put your emoticons/pics in res/drawable folder, you can define an array in your xml file, witch looks like:
<resources>
<array name="emoticons">
<item>#drawable/thumbs_00001</item>
......
</array>
</resources>
In your java code:
int[] emoticonArray = getResources().getIntArray(R.array.emoticons);
Or you can hardcode like this:
int[] emoticonArray = new int[]{R.drawable.thumbs_00001, R.drawable.thumbs_00002, ...};
Then implement your Adapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = new ImageView(mContext);
}
((ImageView)convertView).setImageResource(emotionArray[position]);
return convertView;
}
you need to implement other methods like getCount(), just google 'list adapter'
To set OnClickListener on each item, call
ListView.setOnItemClickListener()
Use a GridView or ListView, they has adapter so they can take care of the onClick easily and they has been designed to display a lot of data.
My web app has a master jade template that contains all the main components that need to be loaded on EVERY page of the app. One of these components is a navbar which I've split out into another template. This navbar has a dropdown that needs to be populated dynamically from a DB.
The problem I'm having is that I want to populate the dropdown at the time that the navbar gets rendered. Because I'm using express 4.0 with nodeJS, I thought of using a helper function that would populate the list straight from within the navbar template. Because this function is async though, the navbar renders itself before the dropdown items are retrieved from the DB.
I also thought of using AJAX on the page load to populate it or even just passing the dropdown items into the template beforehand but I don't want to have to pass in this list on every single res.render() call in my controllers.
What is the best way to go about doing this?
Sample templates
master.jade:
doctype html
html(lang=en)
head
block title
body
#header
include navbar
block headerContent
#content
block content
navbar.jade:
... //nav code
li(class='dropdown')
a(href='#', class='dropdown-toggle', data-toggle='dropdown') List
span(class='caret')
ul(class='dropdown-menu', role='menu')
li
each val, index in list
a(href='#') val
A typical page in the system would just extend the master template and fill in the appropriate header and content blocks.
Thanks!
EDIT:
Adding a sample controller to show render call
sampleController.js:
...some error checking
model.save(function(err, results) {
if (err)
res.render('view', {error: 'some error'})
else
res.render('view', {data: *formatted results obj*})
The data specifically relates with the content that should be rendered on this particular view and not necessarily what's required by the master. I don't want to have to pass in the navbar items as well.
AJAX seems impractical for a navbar.
You can use a middlewear to populate locals object
app.use(function(req,res,next){
res.locals.list = [...];
// or
app.locals.list = [...];
next();
});
I have a site set up in ASP.NET MVC3 right now, but the layout of everything is optimized for mobile devices.
I would now like to combine some of the existing views together to take advantage of the additional screen space in a desktop browser or tablet.
I have two views now, one displaying a list of links and a second displaying some content generated by each link; both these views are handled by separate controllers. Here is the list view (simplified). It uses a layout page, so this is what would be displayed when #RenderBody() is called in the layout (my second view also works like this, with the same layout file).
#model IEnumerable<CommandCenterEntity>
#{
if (Request.Browser.IsMobileDevice) {
Layout = "~/Views/Shared/_LayoutMobileContent.cshtml";
}
else {
Layout = "~/Views/Shared/_LayoutDesktop.cshtml";
}
}
<ul data-role="listview" id="commandcenterlist" data-filter="true" data-inset="true" data-theme="b">
#foreach (var entity in Model)
{
<li>
#Html.CommandCenterLinks(#entity, x => Url.Action("Index", "Worksheet", new { ParentId = #entity.ID_Item }))
</li>
}
</ul>
The CommandCenterLinks helper just generates an "a" tag containing a different icon depending on some properties of the entity.
I'd like to combine my views in such a way that when I click a link in the list, which would be in a div tag on the left of the screen, the generated content will display in a separate div tag on the right.
I was hoping I could reuse the same actions/controllers used in my mobile layout, so I tried using jQuery to intercept the click event on the list and capture the data returned from the action, and inject it into the div:
$(document).on("click", "#commandcenterlist a", function (e) {
$.mobile.showPageLoadingMsg();
$.ajax({
url: this.href,
success: function (data) {
$.mobile.hidePageLoadingMsg();
$("#desktopContentPane").html(data);
}
});
return false;
});
However, the data I get back in the ajax success handler contains the full html page,
<!DOCTYPE html>
<html>
<head>...</head>
<body>...</body>
</html>
...when all I want is the content that would have been generated in the layout's #RenderBody() call. I tried changing the controller method to have return PartialView("Index");, but it gave the same result. Is there a way for me to get back only that portion of the view? Or is there some cleaner, more "MVC" way of going about this?
The best option is really to return your partial view from a separate controller action. So, a few things I would change to make it work:
Take the content you want to share (whatever you want to display in the div for desktop) and put it in a partial view.
Create a controller action which returns just this partial view (use the PartialView method and pass in your partial view name), and call it from your javascript in the desktop version.
In view for the mobile version, you can use the RenderPartial method to include the contents from the partial view in your mobile page.
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').