Parsing error with HTML.Raw and li? - asp.net

I have the following code in my ASP.NET MVC website :
#foreach (var item in Model.Comments.Where(c=>c.CommentId == Model.CurrentNode))
{
if(Model.Level == 0){
#Html.Raw("<li style=\"border:none;\">")
}
else
{
#Html.Raw("<li>")
}
When trying to visit this page I get the following exception :
Parser Error Message: Encountered end tag "li" with no matching start tag. Are your start/end tags properly balanced?
I have tried alot of diffrent options but can´t get this to work.
EDIT 1:
#if (!Model.CurrentNode.HasValue)
{
#Html.Raw("<div class=\"comment-root\" id=\"comment-root\">")
#*hid911 Tells what voteKey to use for this section*#
<input pid="hidVoteKey" type="hidden" value="1" />
}
<ul class="commentList sub">
#foreach (var item in Model.Comments.Where(c=>c.CommentId == Model.CurrentNode))
{
if(Model.Level == 0){
<li style="border:none;">
}
else
{
<li>
}
#if(!item.Deleted)
{
<div class="commentBack">
#if (Request.IsAuthenticated && uFeed.Handlers.AccountHandler.UserContextInstance.Id != item.CreatedBy.Id)
{
#Html.Partial("VotePartial", item.VoteViewModel)
}
else
{
<div style="float:left; width: 30px; "> </div>
}
<div class ="floatLeft" style="width: 90%">
<div class="CommentHeader" id="commentHeader-#item.Id">
<p class="Timestamp dimText">
#Html.ActionLink(item.CreatedBy.Text, "User/" + item.CreatedBy.Text, "Post")
| #item.VoteBalance poäng |
#Html.GetDisplayDate(item.CreatedDate)
</p>
</div>
<div id="commenttext-#item.Id" class="commentText">
#item.Text
</div>
<div id="comment-#item.Id" class="CommentFooter">
#if (Request.IsAuthenticated)
{
<div class="floatLeft">
#Html.ActionLink("Svara", string.Empty, null, new { id= "respond-" + item.Id, href = "#comment", #class = "respond" })
</div>
}
#if (Request.IsAuthenticated && uFeed.Handlers.AccountHandler.UserContextInstance.Id ==item.CreatedBy.Id)
{
<div class="floatLeft" id="divremove-#item.Id">
- #Html.ActionLink("Editera", string.Empty, null, new { id= "edit-" + item.Id, href = "#comment", #class = "edit" })
- #Html.ActionLink("Ta bort", string.Empty, null, new { id="remove-"+item.Id, #class = "remove"})
</div>
<div class="floatLeft hidden" id="divconfirmremove-#item.Id"> - Ta bort?
#Html.ActionLink("Ja", string.Empty, null, new { id = "confirm-remove-yes-" + item.Id, #class = "confirm-remove-yes" })
/
#Html.ActionLink("Nej", string.Empty, null, new { id = "confirm-remove-no-" + item.Id, #class = "confirm-remove-no" })
</div>
}
#if(Model.Comments.Any(c=>c.CommentId == item.Id))
{
#Html.Raw(" - ")
#Html.ActionLink("Dölj kommentarer", string.Empty, null, new { id = "toggle-" + item.Id, Href = "#togglecomments", #class = "toggle active" })
}
<div style="clear:both;"></div>
</div>
</div>
<div style="clear:both;"></div>
</div>
}
else
{
<div class="commentBack">
<div style="float:left; width: 30px; height: 30px"> </div>
<div style="float:left">
<div class="commentText" ><i>[Borttagen]</i></div>
<div id="comment-#item.Id" class="CommentFooter">
#if(Request.IsAuthenticated)
{
<div class="floatLeft">
#Html.ActionLink("Svara", string.Empty, null, new { id= "respond-" + item.Id, href = "#comment", #class = "respond" })
</div>
}
#if(Model.Comments.Any(c=>c.CommentId == item.Id))
{
#Html.Raw(" - ")
#Html.ActionLink("Dölj kommentarer", string.Empty, null, new { id = "toggle-" + item.Id, Href = "#togglecomments", #class = "toggle active" })
}
</div>
</div>
<div style="clear:both;"></div>
</div>
}
<div id="comments-for-#item.Id" class="CommentContainer">
#Html.Partial("CommentPartial", new uFeed.Views.ViewModels.CommentTreeItemViewModel(item.Id, Model.Comments, Model.Level + 1))
</div>
<div style="clear:both;"></div>
</li>
}
</ul>

You don't need the Html.Raw since you are not actually outputting a code variable that contains HTML. This should work just fine:
#foreach (var item in Model.Comments.Where(c=>c.CommentId == Model.CurrentNode))
{
if(Model.Level == 0){
<li style="border:none;">
}
else
{
<li>
}
You could probably simplify this even further...
#foreach (var item in Model.Comments.Where(c=>c.CommentId == Model.CurrentNode))
{
<li #(Model.Level == 0 ? "style=\"border:none;\"" : "")>

Related

How to make sure the page doesn't refresh so my csfile in my razor pages doesn't refresh

I have a project that includes using form post method with buttons. The problem is that it is like a shopping list where each item has 4 chechkboxes and 1 submit "add to cart" when that is pressed it gets in a tabel of purchased items. The problem is that when you press the submit it reloads the page and my Tanks.cshtml.cs file in the Tanks.html gets reloaded so i lose the date inside. So when i add a item to my list it is always gonna be the last one you clicked and not all the ones you clicked. It is in visual studio 2022 ASP.NET core and razor pages.
//cshtml
#for (int i = 0; i < #Model.tanks.Count; i++)
{
if(i == 4)
{
<p> </p>
<b style="color:white; background-color:#fecb2b; margin-left: 10px; margin-right: 10px; font-size: 30px;"> RVS TANKS </b>
<p> </p>
}
if(i == 8)
{
<p> </p>
<b style="color:white; background-color:#fecb2b; margin-left: 10px; margin-right: 10px; font-size: 30px;"> RVS UCO CADDY </b>
<p> </p>
}
<div class="#Model.tanks[i].gallery">
<div class="card">
<img src="~/lib/FotosTanks/#Model.tanks[i].afbeelding" style="width:100%; border-radius: 10px;">
<h1 style="color:#076044">#Model.tanks[i].soort</h1>
<p>Afmetingen: LxBxH (cm)<br> #Model.tanks[i].groote</p>
//here starts the problem
<form method="post">
<input name="PompEnZuigstang" type="checkbox" /> Met pomp & zuigstang<br />
<input name="LengteSlang" type="checkbox" /> Lengte slang (m): <br />
<select class="form-control" name="lengtes" style="width: 190px; color:#076044; margin-left: 18px;" >
<option>4</option>
<option>6</option>
<option>8</option>
<option>10</option>
<option>12</option>
</select>
<input name="Volumemeter" type="checkbox" /> Mechanische volumemeter<br />
<input name="Hittebestendig" type="checkbox" /> Hittebestendig (max. 120°C)<br />
<p> </p>
<input type="hidden" name="id" value="#i">
<p><button style=" border-radius: 4px;" onclick = "onPost(); return false" type = "button">Add to Cart</button></p>
</form>
</div>
</div>
}
//cshtml.cs
public void OnPost()
{
idNummer = Convert.ToInt16(Request.Form["id"]);
optie1 = Request.Form["PompEnZuigstang"];
optie2 = Request.Form["LengteSlang"];
Lengte = Request.Form["lengtes"];
optie3 = Request.Form["Volumemeter"];
optie4 = Request.Form["Hittebestendig"];
if (optie1 == "on")
{
tanks[idNummer].optie1 = "X";
}
else
{
tanks[idNummer].optie1 = "";
}
if (optie2 == "on")
{
tanks[idNummer].optie2 = $"{Lengte}m";
}
else
{
tanks[idNummer].optie2 = "";
}
if (optie3 == "on")
{
tanks[idNummer].optie3 = "X";
}
else
{
tanks[idNummer].optie3 = "";
}
if (optie4 == "on")
{
tanks[idNummer].optie4 = "X";
}
else
{
tanks[idNummer].optie4 = "";
}
Test.Add(tanks[idNummer]);
}
I've been looking for a solution for several hours
If you don't want to refresh the page,you can use ajax to call OnPost:
<button style=" border-radius: 4px;" onclick = "callAjax()" type = "button">Add to Cart</button></p>
<script>
$.ajax({
type: "POST",
url: '',
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
data: $("form").serialize(),
success: function (data) {
...
},
error: function (result) {
alert("fail");
}
})
</script>

Select visible elements in css selectors (querySelector)

Eg.
<div style="display:none">
<span id=test style="display:none"></span>
</div>
I know in jquery you can do :visible
I tried something like :not([display=none]) > span but this will also select nested invisible elements. Eg:
document.querySelectorAll(':not([display=none]) > span').forEach(elem =>
console.log(elem.id)
);
<div id=d style="display:none">
<div id=dd>
<span id=dds></span>
</div>
<span id=ds></span>
</div>
Is there anyone to make a selector that would only accept visible elements?
If there were an AND selector I could do something like the following:
:and(
:not([display=none]) > span,
:not([display=none]) > * > span,
:not([display=none]) > * > * > span,
etc.
)
These are my best workarounds:
function* allVisibleElems(parent = document)
{
for (let elem of parent.children)
{
if (elem.style.display === 'none') continue;
yield elem;
yield* allVisibleElems(elem);
}
}
This function would have equivalent functionality to document.querySelectorAll(':visible').
function isVisible (elem)
{
while (elem !== document)
{
if (elem.style.display === 'none') return false;
elem = elem.parentNode;
}
return true;
}
This function would have equivalent functionality to elem.matches(':visible').
Note: these solutions only work when setting the style.display property to none but that is all I need for my application.
I think you are looking for something like that ?
document.querySelectorAll('span').forEach( sp =>
{
let
pDiv = sp.closest('div')
, pDivOK = true
;
while(pDivOK && pDiv)
{
pDivOK &&= (getComputedStyle(pDiv).display != 'none')
pDiv = pDiv.parentNode.closest('div')
}
if ( pDivOK )
console.log( sp.id, "<-- parents '<div' are all visible")
});
.noDisplay {
display: none;
}
<div id="d" style="display:none">
<div id="dd">
<span id="dds"></span>
</div>
<span id="ds"></span>
</div>
<div id="1d" class="noDisplay">
<div id="1dd">
<span id="1dds"></span>
</div>
<span id="1ds"></span>
</div>
<div id="2d">
<span id="2ds"></span>
</div>

How can I make sematic-ui-react Tab responsive?

I'm developing a react application and I recently start to use semantic ui react module.
Unfortunately I'm not able to make the Tab object responsive...
A really simple script to show this is:
import React from 'react'
import { withRouter } from 'react-router-dom'
import {Tab} from 'semantic-ui-react';
// import NavSection from './NavSection'
var sections = ["SectionA","SectionB","SectionC","SectionD","SectionE","SectionF"]
const NavigatorHeader = () => (
<div>
<h1>Navigator</h1>
<div>
<Tab menu={{ pointing: true }} panes={getPanes(sections)} />
</div>
</div>
)
export default withRouter(NavigatorHeader)
function getPanes(sections){
return sections.map( function(section){
return {
menuItem: section,
render: () =>
<Tab.Pane attacched="false">
<div>
<p>
Some Text that we can change tab from tab. E.g. with the title: <b>{section}</b>
</p>
</div>
</Tab.Pane>
}
})
}
The tabs look great, inline, but if I reduce the screen they just overflow, while I was expecting they would have moved to a second line.
Look like that this is coming from the Selenium-ui css I'm using (https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.css). Current version is 2.3.1 but if I go back to use a version before 2.0.0, it was responsive.. is there a way to obtain the same behavior with the new version?
Thanks,
Michele.
Thanks,
Michele.
Based on the previous answer I found an easier way to achieve this.
I defined a CSS with the values suggested:
.wrapped{
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
and then just passed that additional class to the menu
<Tab menu={{ pointing: true, className: "wrapped" }} panes={getPanes(sections)} />
That solved the problem without any additional javascript.
Here is a solution that I created some time ago in regular Semantic. It behaves like Bootstrap and does not require a second set of menu items. It requires just a tiny bit of JS and CSS.
The JS:
$(function() {
// Set up to handle wrapping of tab menu (tab actuator) items
$(window).resize(function() {
checkIfWrapped();
});
checkIfWrapped(); // Make sure the function is fired upon document ready
});
// Detect whether a Semantic UI tabular menu is wrapped
function checkIfWrapped() {
var pos_top_1st = $('.tabular.menu .item').first().position().top;
$('.tabular.menu .item:not(first-child)').each(function() {
var pos_top = $(this).position().top;
if (pos_top > pos_top_1st) {
$(this).parent().addClass('wrapped');
return;
} else if (pos_top == pos_top_1st) {
$(this).parent().removeClass('wrapped');
}
});
The HTML structure. (Note that placing the .tabular.menu .item-s inside a div within the overall .tabular.menu allows the use of a separate .right.menu within the .tabular.menu if desired) :
<div id="tabs-menu" class="ui top attached tabular menu">
<div id="qj-tabs">
<div class="tab item"></div>
<div class="tab item"></div>
<div class="tab item"></div>
</div>
<div class="right menu">
<a class="tab item"><i class="add icon"></i> Add Job</a>
<a class="tab item"><i class="copy icon"></i> Copy Item</a>
</div>
</div>
<div class="botttom attached tab segment"></div>
<div class="botttom attached tab segment"></div>
</div>
The CSS:
#qj-tabs {
display: flex !important; /* Will not work unless defined as display: flex */
flex-direction: row !important;
flex-wrap: wrap !important;
}
#tabs-menu .wrapped .item {
border-radius: 5px !important;
border: 1px lightgray solid !important; /* Just styling for the default theme here */
margin: 0 2px 2px 0 !important;
}
#tabs-menu .wrapped .active.item {
background-color: lightgray;
}
This is what i did some weeks ago in regular Semanitic-ui.
! function($) {
var WinReszier = (function() {
var registered = [];
var inited = false;
var timer;
var resize = function(ev) {
clearTimeout(timer);
timer = setTimeout(notify, 100);
};
var notify = function() {
for (var i = 0, cnt = registered.length; i < cnt; i++) {
registered[i].apply();
}
};
return {
register: function(fn) {
registered.push(fn);
if (inited === false) {
$(window).bind('resize', resize);
inited = true;
}
},
unregister: function(fn) {
for (var i = 0, cnt = registered.length; i < cnt; i++) {
if (registered[i] == fn) {
delete registered[i];
break;
}
}
}
};
}());
var TabDrop = function(element, options) {
this.element = $(element);
var $this = this;
this.dropdown = $('<div class="ui item right dropdown" data-popup data-content="' + options.text + '" data-position="bottom center">' +
options.icon +
'<div class="menu"></div>' +
'</div>').appendTo($this.element);
this.click = function() {
$this.element.removeClass("pointing");
$this.element.find("a.item").not(this).removeClass("active");
};
this.reverseclick = function(el) {
$this.element.find(".item.right.dropdown .menu a.item").removeClass("active selected");
$this.element.addClass("pointing");
};
WinReszier.register($.proxy(this.layout, this));
this.layout();
$(".ui.dropdown").dropdown();
$("[data-popup]").popup();
};
TabDrop.prototype = {
constructor: TabDrop,
layout: function() {
var $main = this;
var $this = this.element;
var $drpdwn = this.dropdown;
var $fullwidth = $this.width() - 25;
this.element
.append($drpdwn.find('.ui.item.right'))
.find('a.item')
.not('.item.right.dropdown')
.each(function() {
var $blockLenght = parseInt($(this).width());
var $space = $fullwidth - $blockLenght;
if ($space > $blockLenght) {
$(this).click($main.reverseclick)
if ($drpdwn.find('.menu a').length > 0) {
var $reverse = $drpdwn.find('.menu a:first-child');
$reverse.click($main.reverseclick).removeClass("selected")
$reverse.insertBefore($drpdwn);
}
} else {
var $dropItem = $(this)
$dropItem.click($main.click)
$drpdwn.find('.menu').append($dropItem);
}
$fullwidth = $space;
});
}
};
$.fn.tabdrop = function(option) {
return this.each(function() {
var $this = $(this),
data = $this.data('tabdrop'),
options = typeof option === 'object' && option;
if (!data) {
$this.data('tabdrop', (data = new TabDrop(this, $.extend({},
$.fn.tabdrop.defaults, options))));
}
if (typeof option == 'string') {
data[option]();
}
});
};
$.fn.tabdrop.defaults = {
text: 'More',
icon: '<i class="icon align justify m-0"></i>'
};
$.fn.tabdrop.Constructor = TabDrop;
}(window.jQuery);
var Tabs = {
tabDrop: function() {
setTimeout(function() {
$('.tabdrop').tabdrop({
text: 'More Configuration'
});
}, 1000)
}
};
$(document).on("ready", function() {
$('.menu .item').tab();
Tabs.tabDrop();
$(window).resize(function() {
Tabs.tabDrop();
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.3/semantic.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.3/semantic.min.js"></script>
<div class="ui top attached pointing menu tabdrop">
<a class="item" data-tab="tab1">Tab Item 1</a>
<a class="item" data-tab="tab2">Tab Item 2</a>
<a class="item" data-tab="tab3">Tab Item 3</a>
<a class="item" data-tab="tab4">Tab Item 4</a>
<a class="item" data-tab="tab5">Tab Item (A very long tab title)</a>
</div>

Generating one new field in table (ASP.NET MVC)

I have View where I create interview with greeting and details
Here is table
CREATE TABLE [dbo].[Interviews] (
[Interview_Id] INT IDENTITY (1, 1) NOT NULL,
[Greeting] NVARCHAR (MAX) NULL,
[Detail] NVARCHAR (MAX) NULL,
[VacancyId] INT NULL,
PRIMARY KEY CLUSTERED ([Interview_Id] ASC),
CONSTRAINT [FK_Interviews_ToTable] FOREIGN KEY ([VacancyId]) REFERENCES [dbo].[Vacancies] ([VacancyId]) ON DELETE CASCADE
);
Here is my controller for this View
// Страница ввода приветствия и описания вакансии
[HttpGet]
public ActionResult WelcomeScreen()
{
// Формируем список команд для передачи в представление
SelectList teams = new SelectList(db.Vacancy, "VacancyId", "VacancyName");
ViewBag.Teams = teams;
return View();
}
//Заносим инфу о вакансии в таблицу
[HttpPost]
public ActionResult WelcomeScreen(Interview interview)
{
db.Interview.Add(interview);
db.SaveChanges();
//Int32 id = interview.Interview_Id;
//TempData["id"] = id;
return RedirectToAction("Index", "Questions", new { id = interview.Interview_Id });
}
Here is my View
#using (Html.BeginForm())
{
<div class="outer-div">
<div class="inner-div">
<div class="right-welcome-div">
<div class="right-grid-in-grid">
<div class="col-md-10">
#Html.DropDownListFor(model => model.Vacancy.VacancyId, ViewBag.Teams as SelectList, new { #class = "greeting" })
#Html.ValidationMessageFor(model => model.VacancyId, "", new { #class = "text-danger" })
</div>
</div>
<div class="main-left-div">
<div style="margin-left: 40px">
#Html.EditorFor(model => model.Greeting, new {htmlAttributes = new {#class = "greeting", data_bind = "textInput: Greeting", placeholder = "Приветствие", id="Greeting"}})
</div>
#Html.TextAreaFor(model => model.Detail, new { #class = "greeting2", data_bind = "textInput: Detail" })
</div>
</div>
<div class="left-welcome-div">
<div class="text-div" style="padding-top: 30px; word-break: break-all;">
<p style="font-size: 20px; margin-top: 20px; padding-left: 30px; padding-right: 40px; text-align: center;"><b><span data-bind="text: Greeting"/></b>
</p>
<p style="font-size: 20px; margin-top: 40px; padding-left: 30px; padding-right: 40px; text-align: center;"><span data-bind="text: Detail"/>
</p>
</div>
<div class="button-div" style="padding-top: 40px;">
<input style="float: right; margin-right: 30px; margin-top: 20px; border-radius: 12px; width: 200px;" type="submit" value="Создать" class="btn btn-default" />
</div>
</div>
</div>
</div>
<script type="text/javascript">
function ViewModel() {
this.Greeting = ko.observable('');
this.Detail = ko.observable('');
};
var vm = new ViewModel();
ko.applyBindings(vm);
</script>
}
When I click submit button it creates new empty row in Vacancies table.
I don't understand, why??
Why so?
Because you generate dropDownList with name Vacancy.VacancyId according the following code an it will create a instance of Vacancy in property of Interview and When you add Interview in dbContext, EF will create new row for Vacancy because interview.Vacancy is not null.
#Html.DropDownListFor(model => model.Vacancy.VacancyId, ViewBag.Teams as SelectList, new { #class = "greeting" })
Replace the code with this
#Html.DropDownListFor(model => model.VacancyId, ViewBag.Teams as SelectList, new { #class = "greeting" })

Meteor & Handlebars: new row after every N-items

I have this markup:
<div class="row">
{{#each items}}
<div class="col-md-4>{{ItemHere}}</div>
{{/each}}
</div>
I need to group every 3 elements in row, for example:
<div class="row">
<div class="col-md-4>Item1</div>
<div class="col-md-4>Item2</div>
<div class="col-md-4>Item3</div>
</row>
<div class="row">
<div class="col-md-4>Item4</div>
<div class="col-md-4>Item5</div>
<div class="col-md-4>Item6</div>
</row>
...
How can I achieve this with Blaze? Are there any built-in functions or helpers?
I'd create a helper to separate your data into arrays of arrays:
// Helper:
Template.templateName.helpers({
getItemsInGroupsOfThree( array ) {
var result = [];
var currentResultIndex = 0;
for( var i = 0; i < array.length; i++ ) {
if( i % 3 === 0 ) {
if( i !== 0 ) currentResultIndex++;
result.push({ items: [ array[i] ] });
} else {
result[ currentResultIndex ].items.push( array[i] );
}
}
return result;
}
});
//Template:
{{#each itemGroup in getItemsInGroupsOfThree items}}
<div class="row">
{{#each item in itemGroup.items}}
<div class="col-md-4>
{{ItemHere}}
</div>
{{/each}}
</div>
{{/each}}
The helper creates an array of arrays with up to three of your items in each array. You're basically using the created groups to add each row, and then the items within the groups create the columns and output values.
Hope this helps!
You can group the items
//helper
Handlebars.registerHelper('grouping_by', function(groupSize, source, options) {
var out = "", subcont = [], i;
if (source && source.length > 0) {
for (i = 0; i < source.length; i++) {
if (i > 0 && i % groupSize === 0) {
out += options.fn(subcont);
subcont = [];
}
subcont.push(source[i]);
}
out += options.fn(subcont);
}
return out;
});
//template
<div class="container">
{{#grouping_by 3 items}}
<div class="row">
{{#each this }}
{{ item }}
{{/each}}
</div>
{{/grouping_by}}
</div>
this approach let you choose the group size, so you can reuse through your template.

Resources