I have a single-page-application in MVC4 project in C#.
In my HTML I have a like-a-table lists - first is the table titles, and second is in a div with a "foreach" property (knockout) and presents all the items in my list.
Now, I need this "table" to be dynamic - I'll get a list of columns and "instructions" (column title, column class name, column value name, css conditions, etc.) and the HTML will be built dynamically.
Is it possible with knockout?
This is my code now. There are only 5 columns. I need it to be dynamic so I can easily add (and remove) columns by changing the instruction list, whithout touching the HTML.
<ul class="assetsTitles">
<li class="ItemKey" data-bind="click: sortBy.bind($data, 'Key'), css: { selected: Filter().OrderBy() == 'Key', desc: Filter().Descending() }"><span>Key</span></li>
<li class="ItemName" data-bind="click: sortBy.bind($data, 'Name'), css: { selected: Filter().OrderBy() == 'Name', desc: Filter().Descending() }"><span>Item Name</span></li>
<li class="ItemProp1" data-bind="click: sortBy.bind($data, 'ItemProp1'), css: { selected: Filter().OrderBy() == 'ItemProp1', desc: Filter().Descending() }">ItemProp1</li>
<li class="ItemProp2" data-bind="click: sortBy.bind($data, 'ItemProp2'), css: { selected: Filter().OrderBy() == 'ItemProp2', desc: Filter().Descending() }">ItemProp2</li>
<li class="ItemProp3" data-bind="click: sortBy.bind($data, 'ItemProp3'), css: { selected: Filter().OrderBy() == 'ItemProp3', desc: Filter().Descending() }">ItemProp3</li>
</ul>
<div data-bind="foreach: items, visible: items().length > 0">
<div class="itemRow" data-bind=" attr: { id: RowId() }">
<ul class="itemRowDetails " data-bind="visible: ShowDetails, selected: IsSelected, click: $parent.showItemDetails.bind($data, $data, $parent.type), css: { selected: IsSelected() }">
<li class="ItemKey" data-bind=" title: Key"><span data-bind="text: Key" /></li>
<li class="ItemName" data-bind=" title: Name"><span data-bind="text: Name" /></li>
<li class="ItemProp1" data-bind=" title: ItemProp1"><span data-bind="text: ItemProp1" /></li>
<li class="ItemProp2" data-bind=" title: ItemProp2"><span data-bind="text: ItemProp2" /></li>
<li class="ItemProp3" data-bind=" title: ItemProp3Display"><span data-bind="text: ItemProp3Display, css: { alertDetail: ItemProp3Alert, alertDetail2: ItemProp3Alert2 }" /></li>
</ul>
</div>
</div>
you can use ko.renderTemplate
and doing some thing like :
<!-- ko foreach:$root.visibleColumns() -->\
<li data-bind=\"attr:{'data-columnname' : columnName}\" role=\"column\" ><span data-bind=\"attr:{'class': columnHeaderCss, 'data-columnname' : columnName,'data-headertext': headerText}, text: headerText\"></span> </li>\
<!-- /ko -->\
and pass the columns list to viewModel :
ko.dataGrid = {
viewModel: function (configuration) {
var me = this;
$.extend(me, {
columns: configuration.columns,
visibleColumns: function () {
var res = [];
$.each(me.columns, function (i, c) {
if (c.visible)
res.push(c);
});
return res;
},
});
}
You could try building the html in script using traditional techniques then attach it to an element. Then to add this to the binding the name of that element needs to be included as a 2nd parameter:
ko.applyBindings(viewModel, dynamicElement)
Alternatively ko has html ("html:") and text binding ("text:") options.
In constructing the html in code you may need to use the "containerless control flow syntax" i.e. wrap within the comment notation e.g. <!-- ko foreach: myItems --> .... <!-- /ko --> Where myItems is an array.
Usual caveats apply regarding possible injection attacks!
Its been some time since I played with ko..
Related
Having issues accessing the child node of a li element. Looking to print out all text within a list (which acts as a dropdown on the webpage). But all of the text is within an li element under an a> (the third a> tag) tag.
Here is an example of the DOM structure that I am trying to work with. This was given to me and I have no room to change it.
<div class="navbar-collapse collapse" id="navbar-mobile">
<ul class="nav navbar-nav">
<li data-ng-show="!vm.inIdentity" class="dropdown width-250
open">
<a href="" class="dropdown-toggle ng-binding" data-
toggle="dropdown" aria-expanded="true">
<i class="icon-database position-left"></i> Select a
repository <span class="caret"></span>
</a>
<ul class="dropdown-menu width-250 overflow-auto"
style="max-height: 500px">
<li class="dropdown-header">Repositories</li>
<!-- ngRepeat: repository in vm.repositories --><li
data-ng-repeat="repository in vm.repositories"
class="ng-scope" style="">
<a href="" data-ng-
click="vm.selectRepository(repository)"
class="ng-
binding"><i class="icon-database4"></i> **Akzo
Nobel**</a>
</li><!-- end ngRepeat: repository in vm.repositories
--><li data-ng-repeat="repository in
vm.repositories" class="ng-scope">
<a href="" data-ng-
click="vm.selectRepository(repository)"
class="ng-binding"><i class="icon-database4"></i>
AltAir Paramount</a>
</li><!-- end ngRepeat: repository in vm.repositories
-->
IWebElement dropdown = driver.FindElement(By.XPath("//*
[#id='navbar-mobile']/ul[1]/li[1]/ul/li[2]/a"));
Console.WriteLine(dropdown.Text);
IList <IWebElement> ele =
dropdown.FindElements(By.XPath("//li"));
foreach (var li in ele)
{
Debug.WriteLine(li.Text);
}//end foreach loop
I am expecting the values to print out. Values such as "Akzo Nobel", "AltAir Paramount" etc. Which are located under the li elements and a> tags. But for some reason I am only able to see the text of "Select Repository" in the debugger window.
I couldn't find anything regarding my issue so I decided to post one myself.
I am using a navigation bar that has dropdown menu's. Whenever I open the dropdown and navigate to one of those pages, the navigation refreshes and closes the dropdown menu. The dropdown menu needs to stay open when I go over to one of the pages, I tried Model.Content.AncestorOrSelf().Descendants("document") to try and keep the navigation bar from refreshing but that doesn't seem to work (as people said).
Here's my menu structure:
Everything underneath "Hulp per browser" is in a dropdown and will disappear when I click on "Hulp per browser" again.
Here is my code:
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
<div class="col-sm-3">
<div class="NavDigiCampuz">
<h3>Helpcentrum</h3>
<li class="NoBullet"><a class="NormalA" href="https://digicampuz.nl/">Terug naar digicampuz</a></li><br>
<ul class="nav nav-list tree">
#{
var documentRootNodeId = Model.Content.GetPropertyValue("documentRoot", true); // Fetch recursive document root id.
var selection = Umbraco.TypedContent(documentRootNodeId).Children.Where("Visible"); // Select all nodes below the document root.
}
#foreach(var item in Model.Content.AncestorOrSelf(2).Descendants("document").ToList()){
foreach (var ItemChild in #item.Children("categorieMenu")){
if(ItemChild.Children.Any())
{
<li class="MenuItems"><p>#ItemChild.Name</p></li>
foreach (var Subitem in #ItemChild.Children){
if (Subitem.Children("hoofdstuk").Any())
{
<li class="item">
#if(Subitem.GetPropertyValue("hoofdstukIcoon") != "") {
<a class="NormalA aNav" href="#"><i class="fa fa-#(Subitem.GetPropertyValue("hoofdstukIcoon")) fa-fw"></i> #Subitem.Name <i id="Arrow" class="fa fa-arrow-right" style="font-size:10px;" aria-hidden="true"></i></a>
}else{
<a class="NormalA aNav" href="#">#Subitem.Name <i id ="Arrow" class="fa fa-arrow-right" style="font-size:10px;" aria-hidden="true"></i></a>
}
#foreach (var Finalitem in #Subitem.Children){
<ul class="submenu">
#if(Finalitem.GetPropertyValue("hoofdstukIcoon") != "") {
<br><li><a class="NormalA aNav" href="#Finalitem.Url"><i class="fa fa-#(Finalitem.GetPropertyValue("hoofdstukIcoon")) fa-fw"></i>#Finalitem.Name </a></li>
}else{
<br><li><a class="NormalA aNav" href="#Finalitem.Url">#Finalitem.Name</a></li><br>
}
</ul>
}
</li>
}else
{
if(Subitem.GetPropertyValue("hoofdstukIcoon") != "") {
<li><a class="NormalA aNav" href="#Subitem.Url"><i class="fa fa-#(Subitem.GetPropertyValue("hoofdstukIcoon")) fa-fw"></i> #Subitem.Name</a></li>
}else{
<li><a class="NormalA aNav" href="#Subitem.Url">#Subitem.Name</a></li>
}
}
}
}
}
}
</ul>
</div>
</div>
<script>
$(".item").click(function(){
$(this).children(".submenu").toggle(); //it will display or hide your submenu when clicking the item.
});
</script>
<style>
.submenu{
display: none;
list-style:none;
}
</style>
I do plan on removing the script and style from the page when everything works.
First thing you have several issues in the code:
Remove the Where to filter Children and keep it like var selection = Umbraco.TypedContent(documentRootNodeId).Children("Visible");
Cast your hoofdstukIcoon to string Subitem.GetPropertyValue<string>("hoofdstukIcoon")
The first <li class="noBullet"> should be in your nav-list, not outside.
You shouldn't put <br> between your list items, if you want margins use css.
Now we'll focus on your issue with the submenus. What you are doing with your javascript is just using the display property to hide or show your submenu but when the page is rendered, Razor has no idea if that should be hidden or not. To solve this you have to create a new class like .visible that can be used by Razor and Javascript.
Yous hould also move your <ul class="submenu"> out of your #foreach (var Finalitem in Subitem.Children) because what you are doing now is creating a new list with one item for each one.
You should also include a conditional before your submenu in case there a no children and we don't want submenu #if (Subitem.Children.Any()) {
The way of telling your submenu with Razor if it has to diplay or not is doing this:
var isVisible = Model.Content.IsDescendantOrSelf(Subitem) ? "visible" : "";
<ul class="submenu #isVisible">
So in that example your submenu will show if the current page is this Subitem or one of its children.
And your JS script would become this:
$(".item").click(function () {
$(this).children(".submenu").toggleClass('visible'); //it will display or hide your submenu when clicking the item.
});
And your CSS this:
<style>
.submenu {
display: none;
list-style: none;
}
.submenu.visible {
display: block;
}
</style>
I have list of items in database
ITEMS
I_id int,
I_name varchar(50),
I_order int
I displayed it in ul li
<ul id='items'>
<li><span class='txt'>item-1</span> <span class='mOrder'>1</span></li>
<li><span class='txt'>item-2</span> <span class='mOrder'>2</span></li>
<li><span class='txt'>item-3</span> <span class='mOrder'>3</span></li>
<li><span class='txt'>item-4</span> <span class='mOrder'>4</span></li>
<li><span class='txt'>item-5</span> <span class='mOrder'>5</span></li>
<li><span class='txt'>item-6</span> <span class='mOrder'>6</span></li>
<li><span class='txt'>item-7</span> <span class='mOrder'>7</span></li>
<li><span class='txt'>item-8</span> <span class='mOrder'>8</span></li>
<li><span class='txt'>item-9</span> <span class='mOrder'>9</span></li>
</ul>
<input type='button' id='btnSave' value=' Save order ' />
sorted through jquery sortable plugin
$(".items").sortable({
$(".items li").each(function () {
var OrderNum = (parseInt($(this).index()) + 1);
$(".mOrder", this).html(OrderNum);
});
});
now I want to save new order
I have saveOrder.ashx file to update records in database
I have problem while sending data in ajax
I am trying as below
$("#btnSave").click(function(){
var arr=[];
$(".items li").each(function () {
arr.push({'m'+$(this).index():$(".txt",this).html()});
//m0:item1, m1:item2,....
});
$.ajax({
url:'',
data:arr;//here is problem
});
});
I am sending this but it is not accessable in saveOrder.ashx
I can try any alternative
I may have 2 answers:
wrap the array in a JSON object:
url:'',
data: {'arrayofObjects':arr}
JSON.stringify()
url:'',
data: JSON.stringify(arr)
ADDITIONAL:
JSON.stringify() + JSON object wrap
url:'',
data: JSON.stringify({arrayofObjects:arr})
I would like to add multiple jquery sliders on a cshtml page using data from a database. Basically I have a collection of tabs that when active dynamically populate a slider contained within with data from a database.
cshtml code with Razor C# hooks:
<div class="tabbable">
<ul id="myTab" class="nav nav-tabs">
#foreach(var row in db.Query(queryCategory))
{
<li>#row.Food_Category</li>
}
</ul>
<div class="tab-content">
#{bool first = true;}
#foreach(var row in db.Query(queryCategory))
{
var ids= #row.Food_Category;
<div class="#{if (first){<text>tab-pane active</text> first = false;}else{<text>tab-pane</text>}}" id=#ids>
<p>I'm in #row.Food_Category.</p>
<div class="list_carousel">
<ul id="foo">
#foreach(var row1 in db.Query("SELECT * FROM Food WHERE Food_Category = #0", ids))
{
<li>#row1.Food_ID</li>
}
</ul>
<div class="clearfix"></div>
<a id="prev2" class="prev" href="#"><</a>
<a id="next2" class="next" href="#">></a>
<div id="pager2" class="pager"></div>
</div>
</div>
}
</div>
</div><!--tabbable-->
The bit I think needs focus:
The rest of the code is dynamic except this bit. I'm not sure how to go about getting a unique id for each un-ordered list (e.g foo1, foo2, foo3 dynamically) depending on the number of items in a database column.
<ul id="foo">
#foreach(var row1 in db.Query("SELECT * FROM Food WHERE Food_Category = #0", ids))
{
<li>#row1.Food_ID</li>
}
</ul>
The Jquery bit:
Here Im not sure, but I think I'll need to set this options true for a range of #id specified dynamically.
<script>
//Carousel
$('#foo').carouFredSel({
width: '100%',
scroll: 2,
auto: false,
prev: '#prev2',
next: '#next2',
pagination: "#pager2",
mousewheel: true,
swipe: {onTouch: true}
});
</script>
I'm just starting out with webmatrix & jquery please bear with me. Thanks
If you just want to get the unique ID for each unorder list you can do somethink like this
#int inc=0;
#foreach(var row in db.Query(queryCategory))
{
var ids= #row.Food_Category;
<div class="#{if (first){<text>tab-pane active</text> first = false;}else{<text>tab-pane</text>}}" id=#ids>
<p>I'm in #row.Food_Category.</p>
<div class="list_carousel">
<ul id="foo#inc++">
#foreach(var row1 in db.Query("SELECT * FROM Food WHERE Food_Category = #0", ids))
{
<li>#row1.Food_ID</li>
}
</ul>
<div class="clearfix"></div>
<a id="prev2" class="prev" href="#"><</a>
<a id="next2" class="next" href="#">></a>
<div id="pager2" class="pager"></div>
</div>
</div>
}
but if you just want to get carousal dynamically for-each under list you can use for each function in jquery foreach
$('ul').each(function(index) {
$('this').carouFredSel({
width: '100%',
scroll: 2,
auto: false,
prev: '#prev2',
next: '#next2',
pagination: "#pager2",
mousewheel: true,
swipe: {onTouch: true}
});
});
I have an list that toggles with no problem in FF. I need this working IE for it to be production ready.
It seems (IE) to apply the js to the first #orderItem and the first #familiy only. The rest of the items in the list are ignored.
Any help would be great.
A piece of the HTML (large list):
<div class="classificationContainer">
<ul class="classification" id="orderUL">
<li id="orderItem" class="ordrheading">
<div class="order">
<a href="?nav=search_recherche&lang=en">
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_closedc.gif" alt="By Classification" id="OrdListImage" />
Apodiformes (Swifts and Hummingbirds)
</a>
</div>
<ul class="classification" id="FamilyList">
<li id="familiy">
<div class="family">
<a href="?nav=search_recherche&lang=en">
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_closedc.gif" alt="Family" id="FamListImage" />
Apodidae (Swifts)
</a>
</div>
<ul class="classification" id="SpiecesList">
<li>
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_leafc.gif" alt="Species" />
Chimney Swift (Chaetura pelagica)
</li>
</ul>
</li>
<li id="familiy">
<div class="family">
<a href="?nav=search_recherche&lang=en">
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_closedc.gif" alt="Family" id="FamListImage" />
Trochilidae (Hummingbirds)
</a>
</div>
<ul class="classification" id="SpiecesList">
<li>
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_leafc.gif" alt="Species" />
Ruby throated Hummingbird (Archilochus colubris)
</li>
<li>
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_leafc.gif" alt="Species" />
Rufous Hummingbird (Selasphorus rufus)
</li>
</ul>
</li>
</ul>
</li></ul></div>
I have the following jquery functions:
<script type="text/javascript">
$(document).ready(function () {
// toggle action for the order to familiy
$("li#orderItem").click(function (event) {
// toggle the image
var src = ($("#OrdListImage", this).attr("src") == "/images/node_closedc.gif")
? "/images/node_openc.gif"
: "/images/node_closedc.gif";
$("img#OrdListImage", this).attr("src", src);
//toggle the ul
$('ul#FamilyList', this).toggle($('ul#FamilyList', this).css('display') == 'none');
// stop all link actions
return false;
});
//toggle action from familiy to speices
$("li#familiy").click(function () {
// toggle the image
var src = ($("#FamListImage", this).attr("src") == "/images/node_closedc.gif")
? "/images/node_openc.gif"
: "/images/node_closedc.gif";
$("img#FamListImage", this).attr("src", src);
//toggle the ul
$('ul#SpiecesList', this).toggle($('ul#SpiecesList', this).css('display') == 'none');
// stop all link actions
return false;
});
});
Also check if id's are not repeated (there is only one #orderItem, only one #familiy and etc.). "id" attribute must be unique in html document, "class" can be repeated.
The toggle function provided by jQuery is not guaranteed to work. I lost the reference where I read this (was on jQuery's homepage). I encountered the same problem and (as suggested by jQuery) implemented my own toggle function. I'd suggest trying this, as it's not much work and could provide you a solution.