I am struggling with passing all the data I need to a controller in MVC. The code is as follows:
<td><a href=#Url.Action("AddCourseToStudentPlan", "Users", new {
courseID = c.CourseId, userID = user.UserId, semNum = num}) title="Add Course
to Semester" >"Here"</a></td>
(currently num is defined as var num = 1;, which of course won't work.)
The course ID's and userID's are passing fine. these values are coming from a ViewBag essentially.
However, semNum is dependent on something entirely different:
<ul class="nav nav-tabs" id="Semtabs">
#{ var year = plan.CatalogYear; }
<li class="active">Fall #year</li>
#{ year += 1; }
<li class="">Spring #year</li>
<li class="">Fall 2014</li>
<li class="">Spring 2015</li>
<li class="">Fall 2015</li>
<li class="">Spring 2016</li>
<li class="">Fall 2016</li>
...
The intended output is that when the user clicks on one of the tabs, they see a list of courses that they have added, and are able to add courses to this tab by clicking on the link in the code previous code block. Therefore, clicking on a tab should change the value of num in the #Url.Action() method. But of course I can't do this because C# is server side.
So the problem is, how am I able to pass some variable semNum (which is determined client-side) to the #Url.Action() method after the page loads?
There are multiple ways to do it. This one is fairly intuitive and will not cause syntax errors in Visual Studio.
Create a URL template with the info you know.
When the link is clicked, look at the current state of the tabs.
Use that information to complete the URL.
Navigate as desired.
<!-- define a link/button, but don't set the URL -->
<a id="add-url-button">Add Course to Semester</a>
<!-- your existing tabs -->
<ul class="nav nav-tabs" id="Semtabs">
<li>Tab 1</li>
<li class="active">Tab 2</li>
<!-- etc. -->
</ul>
<script>
// Create a URL template
// It sounds like semNum is the only value that needs to vary,
// but you can create a template with multiple placeholders.
// We pass zero for semNum so that routes will still match without
// conflicting with a real semester number.
var addUrlTemplate = '#Url.Action("AddCourseToStudentPlan", "Users", new { courseID = c.CourseId, userID = user.UserId, semNum = 0 }';
// jQuery here for brevity (will work fine with vanilla JS)
var addButton = $("#add-url-button"),
tabs = $("#Semtabs");
addButton.click(function(){
// determine the selected tab by interrogating the list of tabs
var activeTab = tabs.find("li.active"),
semesterNumber = activeTab.attr("semester-numer");
// Construct the complete URL. Depending on the URL, you may need
// a smarter regex. Be sure that there is no chance of accidentally
// replacing the wrong value.
var addUrl = addUrlTemplate.replace(/0$/, semesterNumber);
// navigate as desired
window.location.href = addUrl;
));
</script>
Related
I have a table that is populating with ng-repeat, and I also have navigation button that change table data. Before I had custom filter on the data in html file, like so:
ng-repeat="car in carList | filter:tableFilter"
Even so it worked, it slowed my website, a lot. So now I am updating my table data in my controller. But there is another problem, ng-repeat do not want to update. So no matter how much I will update my data, the table will be still the same.
How can I fix that?
Here is my ng-repeat:
<tbody>
<tr ng-repeat="car in sortedCarList">
....
Here is my nav-bar:
<section class="tab" ng-controller="TablePanelCtrl as panel">
<ul class="nav nav-pills car-navigation">
<li ng-class="{ active: panel.isSelected(1)}">
<a href ng-click="panel.selectTab(1); initCarList(1); resetActiveRow(); formattedTable(2); hideTypeBox()">Sort by Reviews</a>
</li>
<li ng-class="{ active: panel.isSelected(2)}">
<a href ng-click="panel.selectTab(2); initCarList(2); resetActiveRow() formattedTable(2); hideTypeBox()">Sort by Rating</a>
</li>
</ul>
initCarList() changes the data according to tab number.
formattedTable() filters table data according to filter values that can be changes by user.
UPDATE:
my formatting function:
$scope.formattedTable = function(index){
$scope.initCarList(index);
$scope.sortedCarList = [];
var carlistLength = $scope.carList.length;
for (var i=0;i<carlistLength;i++){ // just check every row if values passes user requirements
var rowBool = $scope.tableFilter($scope.carList[i]);
if (rowBool){
$scope.sortedCarList.push($scope.carList[i]);
}
}
}
While I agree with cerbrus that we need to see a bit more of your code, I'll take a stab in the dark : you call formattedTable(2) in both tabs, which means that your filtering never changes.
I am making an angularJS app that uses ng-repeat and a combination of filters as a simple type of controller. I did this so that users could both search and click their way through the site.
My side-bar nav looks like this:
<li><a ng-click="navFilter = {type: 'section1'}" >Section 1</a></li>
<li><a ng-click="navFilter = {type: 'section2'}" >Section 2</a></li>
<li><a ng-click="navFilter = {type: 'section3'}" >Section 3</a></li>
Which is also works with a search filter:
<input ng-click="Filter = null" type="text" ng-model="searchFilter">
When the user clicks on the search box, "Filter" the filter triggered by the side-bar nav is set to null and the user can search all contents of the site.
<div ng-repeat="item in items | filter:navFilter | filter:searchFilter">
<div>{{item.title}}</div>
<div>{{item.body}}</div>
</div>
I am concerned about what happens when a user hits the back button. Is there an "Angular" way to configure a router such that when a user hits back, the URL causes the filter to go to its previous state?
If you want to support browser buttons, better to add the filters in the query string parameters. Then use $routeParams to extract the filters to apply. Set the searchFilter and navFilter in the controller using these routeParams.
This would cause view reload but this can fixed by setting $routeProvider reloadOnSearch=false. See documentation here
i have created a web application in asp.net with C# and MySql Database at the backend called simple online shopping,
I have created a cascading dropdown horizontal navigation menu (navmenu) with unordered lists and html hyperlinks. i have 2 pages Homepage.aspx and ShowProducts.aspx.
Navmenu contains the categories in an hierarchy and the products and category data is stored in databases.
when a hyperlink is clicked on the navmenu i wanted the to show the products contained in the category in the ShowProducts.aspx
i have list item in unordered lists in navmenu in hierarchy of
1.Clothing
1.1:Mens
1.1.1:Shirts
1.1.2:Trousers
1.1.3:WinterWear
1.2:Womens
1.2.1:Casual Wear
1.2.2:Jeans
1.2.3 Bags
I have wrote the hyperlinks as:
<ul id="navmenu">
<li>Clothing
<ul class="sub1">
<li>Mens
<ul class="sub2">
<li>Shirts</li>
<li>Mens Trousers</li>
<li>Jeans</li>
<li>Winter wear</li>
<li>Watches & Bags</li>
<li>Footwear for men</li>
</ul>
</li>
<li>Womens
<ul class="sub2">
<li>Sarees & Dresses</li>
<li>Jewellery</li>
<li>Womens Jeans</li>
<li>Womens Bags</li>
<li>Footwear for Women</li>
</ul>
</li>
</ul>
</li>
I am using Devart linqconnect(Linq To MySql). some one told me to use querystrings to pass data between pages but it contains images and data so i wanted to use repeaters to show them in hiererchy. Could add an onlick handler to<a> tag so and write a javascript function
such as
<script type="text/javascript">
Function showproducts() {
-- Linq code to retrieve products based on id --
}
could anybody suggest a good method or tell how can i achieve this.
thanks.. please help me on this..
Use Repeater to render list of links on your page. Add query string value like ShowProduct.aspx?id=1 to every link.
On ShowProduct Page, use linq to retrieve data from DB:
using(DataContext db = new DataContext())
{
int id = Convert.ToInt32(Request.QueryString["id"]);
var product = db.products.Where(p => p.id = id).FirstOrDefault();
if(product != null)
{
//do your job here with product data
}
}
I want to implement dynamic breadcrumb and really dont know how do i go about it. Cant find much examples on internet. Please see attached image where i have added breadcrumb. The code for it as below
<div style="font-size: 10px;">
<ul class="breadcrumb">
<li>
Home <span class="divider">></span>
</li>
<li>
<li><a id="navObject" href="../AgrProduct/Index.aspx" class="active" >Search</a></li>
</ul>
</div>
Currently i have just 2 level in breadcrumb as Home and Search. when i click on button Search it will show me list of products and when i select one on product the breadcrumb should show as Home > Search > Product. I am also attaching image of what happens when i click on Search button
Please let me know how should i go about it. I am really stuck. I use knockout,jquery.
Well, if you created a breadcrumb view model:
var breadCrumbViewModel = function()
{
var self = this;
self.breadCrumbs = ko.observableArray();
self.addCrumb = function(url, text, active)
{
self.breadCrumbs.push({ 'url': url, 'text': text, 'active': active });
}
self.reset = function()
{
self.breadCrumbs.removeAll();
}
}
And then use it something like this (I've not tested this, so there may be some errors in it, but the idea should be good!)
<ul class="breadcrumb" data-bind="foreach: breadCrumbViewModel.breadCrumbs">
<li>
<a data-bind="attr: { href: url }, text: text, css: { active: active }"></a> <span data-bind="visible: $index < breadCrumbViewModel.breadCrumbs - 1" class="divider">></span>
</li>
</ul>
You would set it up in the function called whenever you navigate to a "page" within your SPA:
function()
{
breadCrumbViewModel.reset();
breadCrumbViewModel.addCrumb('#/Home', 'Home');
breadCrumbViewModel.addCrumb('#/Product/:id', 'Search', true);
}
Don't forget to bind the model the the html element for knockout to do its stuff.
I'm using the example code for sammy.js for the navigation, though I will admit that I haven't used sammy.js before, I've got a custom implementation of navhistory.js from the Microsoft Big Shelf SPA example. But that should be enough to give you a head start on it. I'm assuming that you actually want this to be a SPA, despite having actual URLs in your links that would take you off to another page.
I need to use a Javascript variable (defined in the front-end) in some EJS code, as follows:
var selected = 1;
<% for (var i=0; i < supplies.length; i++) { %>
if (i == selected) {
console.log(supplies);
}
<% } %>
I'm using EJS, Express.js and socket.io. I could convert the Javascript variable to an EJS variable by sending a message to my Node.js server instance, but that's kind of silly... Is there a way to use Javascript variables inside EJS?
EDIT:
I want to access supplies, a javascript array, after the user selected an item from a drop down menu. When he selects this item, a javascript function with the above code needs to access some EJS. That's why I need to use a normal Javascript variable in EJS.
Can I pass a JavaScript variable into a template?:
It is possible to get more data into the template and re-render it, but not in the manner that you're thinking, and without making another request to the server (unless it's to get more data, not to get more HTML).
Solution:
This question is going to be difficult to answer without more details, so I'm going to make some assumptions about why you want to pass a selected value into an EJS template. I'll do my best to answer this with limited information about your goals.
It seems like your user is performing some action on the page, like selecting a cleaning supply, and you want to render the data differently, based on which element the user selected. To do this, you can re-render the template and pass in data that identifies which element is selected, using a view helper to apply a specific class to the selected element:
Here is the modified cleaning.ejs template, with the class added using the view helper:
cleaning.ejs:
<script>
// NOTE: even if uncommented, JavaScript inside a template will not run.
// var selected = 1;
</script>
<h1><%= title %></h1>
<ul>
<% for(var i=0; i<supplies.length; i++) { %>
<li>
<!-- apply a class to the selected element -->
<a class='<%= supplies[i].selected %>' href='supplies/<%= supplies[i].value %>'>
<%= supplies[i].value %>
</a>
</li>
<% } %>
</ul>
The rendered HTML looks like this:
<script>
/** NOTE: Script blocks will not fire in rendered templates. They are ignored
// var selected = 1;
</script>
<h1>Cleaning Supplies</h1>
<ul>
<li>
<a class="" href="supplies/Broom">
Broom
</a>
</li>
<li>
<!-- Note the selected element -->
<a class="selected" href="supplies/mop">
mop
</a>
</li>
<li>
<a class="" href="supplies/Hammer">
Hammer
</a>
</li>
</ul>
This view was rendered using the following JavaScript code:
// modified data structure so that array of supplies contains objects
// with the name of the item and whether or not it's selected.
data = {
"title":"Cleaning Supplies",
"supplies":[
{
"value":"Broom",
"selected":""
},
{
"value":"mop",
"selected":"selected"
},
{
"value":"Hammer",
"selected":""
}
]
};
// pass data into template and render
var html = new EJS({url: 'cleaning.ejs'}).render(data);
// add HTML to the DOM using a <div id="container"></div> wrapper.
document.getElementById("container").innerHTML = html;
As you can see, supplies[i].selected applies the selected class to the element that was marked as selected in the data structure. I modified the href value so that it accessed the object in the ith array item instead of the value of the array itself.
Now, when the selected item is modified, we simply modify the data variable, re-render the EJS template, and add it to the DOM.
With this CSS in the head of your HTML document, you'll see something similar to what's displayed below:
<style>
.selected { color:red; }
</style>
Why JavaScript in the template doesn't run:
The method that you're attempting to use to manipulate JavaScript values or use JavaScript values inside the EJS template won't work. This has to do mainly with the context of when the JavaScript is executed.
You're right to think that the EJS templates are compiled on the client-side. However, the JavaScript in the view helpers are executed independent of the JavaScript in the Global context. From looking at the ejs.js source code, it appears as if eval is used in the process.
Additionally, EJS returns the rendered HTML as a string, and the documentation for EJS instructs us to inject that rendered template string into the DOM using innerHTML:
document.getElementById("container").innerHTML = html;
No matter what view technology you're using, one of the fundamental truths of some browsers when it comes to JavaScript is this: Some browsers may not evaluate <script> blocks added to the DOM using innerHTML.
In other words, in my test template, when I tried adding a script tag to output the selected value to the console, I could see that the script block was added, but due to the way innerHTML works, it was not executed:
Example Template Demonstrates JavaScript won't run if added using innerHTML:
<h1><%= title %></h1>
<ul>
<% for(var i=0; i<supplies.length; i++) { %>
<span id="selected"></span><script>console.info('test <%= i %> = <%= supplies[i] %>');</script>
<li>
<a href='supplies/<%= supplies[i] %>'>
<%= supplies[i] %>
</a>
</li>
<% } %>
</ul>
Rendered HTML:
As you can see below, the console.log statements are present in the HTML. However, when added using innerHTML, they will not fire.
The approach to take with view technologies is to limit their use to just that, rendering the view. Keep your logic in the "regular JavaScript".
<h1>Cleaning Supplies</h1>
<ul>
<span id="selected"></span><script>console.info('test 0 = Brrom');</script>
<li>
<a href='supplies/Brrom'>
Brrom
</a>
</li>
<span id="selected"></span><script>console.info('test 1 = mop');</script>
<li>
<a href='supplies/mop'>
mop
</a>
</li>
<span id="selected"></span><script>console.info('test 2 = Hammer');</script>
<li>
<a href='supplies/Hammer'>
Hammer
</a>
</li>
</ul>
More examples and documentation can be found on EJS Templates on the Google Code Embedded JavaScript site.