If statement is not evaluated correctly - razor

I am trying to evaluate a property of a model to see if it is empty before attempting to render a HiddenFor HTML element, but the code block of the if statement is entered, even if the statement is false.
#{
if(Model.BoatImage.UploadedImagePath != string.Empty)
{
#Html.HiddenFor(model => model.BoatImage.UploadedImagePath)
}
}
In the code above, UploadedImagePath is initialized to string.Empty in BoatImage's constructor. If I break at the if statement, Intellisense shows that UploadedImagePath is empty, and the Immediate window evaluates the if statement to be false. However, the program still attempts to render the HiddenFor element.
EDIT: The debugger incorrectly noted that the code above was causing the exception, when actually is was a couple of lines below the code above. Once I corrected the line that was causing the issue, the code above works correctly.

in razor you should write like this:
#if(!string.IsNullOrEmpty(Model.BoatImage.UploadedImagePath))
{
#Html.HiddenFor(model => model.BoatImage.UploadedImagePath)
}
Please note that I also changed your string evaluation method

Related

How do I find the name of this control? "Cannot read property 'focus' of null"

I am trying to focus an element of web.whatsapp.com.
I use "Inspect" in Chrome to find its name.
As I read it, the name is
div.Er7QU.copyable-text selectable-text"
However, when I call ".focus()" on it...
document.querySelector("div.Er7QU.copyable-text selectable-text").focus();
I receive the error
Cannot read property 'focus' of null.
What am I doing wrong?
In Chrome, it looks like this:
You must use document.querySelector("div.Er7QU.copyable-text.selectable-text").focus();
You need to concatenate all class names via the . (also, this is exactly what appears on your screenshot. There are no spaces between the classes)
Also, as #Rick mentioned, make sure to protect the code by using a conditional statement that will check whether the selector returned null before running any methods on the element selected.
document.querySelector("div.Er7QU.copyable-text selectable-text") is returning null. code it like this to avoid errors, but something else is wrong with your code:
var el = document.querySelector("div.Er7QU.copyable-text selectable-text");
if (el)
{
el.focus();
}
else
{
alert('Element not found.');
}

Blazor component is initialized, but not visible?

I am working a bit with blazor right now and got to a pretty weird fault.
So, I´ve got a parent component, which is having a child component and this is having a child component itself, both giving an Object to the child component. Something like that:
Parent.razor
<ChildComponent #bind-Model="Model" ObjectListConverted="ObjectListConverted"/>
#code {
List<Object> ObjectListConverted = new List<Object>();
}
and
Childcomponent.razor
<MyOwnChild Item="#((Item)obj)"/>
So far, so good. Now, there is the interesting thing happening. The Parent and the Childcomponent are both being initialized straight at loading the page. The MyOwnChild-Component can only be loaded after converting some stuff, which happens in the onInitialized()-method of Childcomponent.razor. I checked, if the conversion is working and in fact the MyOwnChild-component is being initialized (which I checked via logging), but it´s not visible. I tried to use a testComponent, just containing a -Tag with some content, but it´s also not displayed. Also checked the html, that´s generated for hidden-divs, either due to css or due to a missassigned hidden attribute, but nothing like that is found.
It´s pretty weird. What´s probably important to know is, that the MyOwnChild is using itself recursive if obj is expanded, but this is false by default.
Additionally it is bound in a bigger context, so the ChildComponent.razor is actually containing two foreach-loops, one with the converted stuff, one with another list, that´s only getting items added on user interaction:
Childcomponent.razor
#foreach (Object obj in ObjectListConverted)
{
if (obj.IsFolder) //This evaluates to true in all cases right now.
{
<MyOwnChild Item="#((Item)obj)"/>
Console.WriteLine("Hey, it´s a folder!"); //This is logged.
}
}
#if (Model.OtherList != null)
{
#foreach (DetailedObject obj in Model.OtherList)
{
if (obj.IsFolder)
{
<MyOwnChild Item="#((Item)obj)"/>
}
}
}
#code {
[Parameter]
List<Object> ObjectListConverted {get; set;}
[Parameter]
Model Model {get; set;} = new Model();
protected override void OnInitialized() {
ObjectListConverted = ConvertToStructuredList(Model.List);
base.StateHasChanged();
}
}
So while the upper version on the MyOwnChild.razor is not displayed at any time at all, though initialized, there´s no problem with it being displayed after adding a new item to the otherList. The inheritance is as follows:
Item:DetailedObject:Object
But I don´t think that´s the problem, cause the extension DetailedObject is only having a additional attribute content, which is not used at all here.
Thanks for help. :)
So I fixed the issue myself now.
It was pretty tricky.
So the problem was as follows:
The ObjectlistConverted in the ChildComponent is a parameter, cause it is planned to be bound to a parents list.
At the state of the error it was not bound yet.
So OnInitialization of the ChildComponent the Parent is giving the empty list to it to prevent the ModelListConverted of being null. As the OnInitialized-method calls the conversion method it changes the ModelListConverted to another reference. Cause it is not bound to the parent, the parent is still holding the old list not updating the reference. When base.StateHasChanged()is called everything is rerendered. The parent sees, that the reference of the childcomponent is not the actual one anymore and gives it the old reference a second time. Cause it is only rerendered and not initialized again, it is not converting the list a second time, preventing the program from throwing a stack overflow error or getting into an endless loop. It´s just taking the empty list now, so right after initializing the MyOwnChild-component it removes it again, cause there´s no item in the list for it anymore.

Scala Play template vararg HtmlContent

I have a generic template in play 2.6, that I want to pass in a variable amount of HtmlContents. I've defined the template like this (including the implicit parameter I have in case that changes anything):
#(foo: String)(content: Html*)(implicit bar: Bar)
On the template side, this works fine-- I can dissect content with for and render it as I want. However, I haven't been able to figure out a clean way to invoke the variable arguments from the underlying template.
e.g, I have a view named "Baz":
#(something: String)(implicit bar: Bar)
In it, I try to invoke the template with multiple Html arguments. I've tried the following:
#template("fooString"){{123},{abc}}
and
#template("fooString")({123}, {abc})
and
#template("fooString"){{123}, {abc}})
And various other permutations, but inside of an enclosing bracket it seems to interpret everything literally as a single parameter in the HtmlContent vararg.
However, this ended up working as I intended, passing in multiple HtmlContents:
#template("fooString")(Html("123"), Html("abc"))
So that works, and I can use a triple-quoted interpolated string for a large Html block-- but it seems like there should be a cleaner way to do this, and the string interpolation is dangerous as it doesn't do html escaping.
Is there a way to do this using the { enclosed syntax? I'd like to understand more what is actually happening on an underlying level, and how play parses and generates HtmlContent in brackets.
So consider you have below template
// main.scala.html
#(title: String)(contents: Html*)
There are different ways you can call this template
Option #1
This is what you already posted in the question
#main("This is a title")(Html("abc"), Html("123"))
Options #2
#html1 = {
Hello
}
#html2 = {
<div>Tarun</div>
}
#main("This is a title")(html1, html2)
Option #3
#main("This is a title")(Html(<div>Tarun
</div>.toString), Html(<div>
Lalwani
</div>.toString))
Options #4
This is not exactly same option, but needs change in Template signature itself
#(title: String)(contents: List[String])
And then calling it like below
#main("This is a title")(List(
"""<div>
Tarun
</div>
""", """Hello"""))
Option #5
This requires code files and was already answered on another SO thread
Paul Draper's answer on Why doesn't this pass multiple HTML parameters to template

How to use COMMENTS channel without getting a warning

I read the answer to Why am I getting an error when assigning tokens to a channel?.
The answer is that this is not an error, but a warning.
Well that's all very well, but the Eclipse IDE, https://github.com/jknack/antlr4ide, will not generate code when this warning is present.
Is there a way to not get a warning, when using a COMMENT channel?
You could trick the compiler by defining COMMENT in a tokens{} block instead of in the #members{} block. This would result in a constant value getting automatically assigned to it.
If you are also using the HIDDEN channel, I would include something like this to be safe:
#members {
{
if (HIDDEN == COMMENT) {
throw new IllegalStateException(
"Expected the HIDDEN and COMMENT constants to have different values.");
}
}
}

Trim not working in Coldfusion 8.0

I am trying to trim a string returned by one of my Coldfusion component but whatever I do Coldfusion add line feed at the start of the String without any reason resulting in an error in my Javascript. Do you have any idea of what's wrong with this code?
function back(){
window.location = <cfoutput>"#Trim(Session.history.getBackUrl())#"</cfoutput>;
}
The code above produce the following peace of HTML:
function back(){
window.location = "
http://dummy_server_address/index.cfm?TargetUrl=disp_main";
}
Looking at the Coldfusion specs here is the trim definition :
A copy of the string parameter, after removing leading and trailing spaces and control characters.
So it should have done the job! I am therefore wondering how to do that properly, I don't want to use replace or some similar function.
EDIT : very surprisingly this is working... but I don't like this solution, so if you have any other idea, or at least explanations about this behaviour.
<cfset backUrl = Session.history.getBackUrl()>
function back(){
window.location = <cfoutput>"#backUrl#"</cfoutput>;
}
Make sure your History component has output disabled. i.e:
<cfcomponent output=false >
Then make sure the getBackUrl function (and every other function) in the CFC also has output=false set.
Also, don't forget to use JsStringFormat on the variable, to ensure it is appropriately escaped:
<cfoutput>"#JsStringFormat( Session.history.getBackUrl() )#"</cfoutput>
Otherwise, there's a potential risk for JavaScript injection, or just JS errors, if the URL happens to contain ".
I've tested your current code and it works fine for me, I suspect that your CFC might be returning more then you think, which I obviously can't duplicate. I would personally always ensure that the component returns 'clean' results rather then removing junk characters after the fact :)
I have had similar issues in the past and it has always turned out to do with cfoutput, never got to the bottom of it. As a starting point I would rewrite this way and see if it makes a difference...
<cfset variables.stWindowLocation = '"' & Trim(Session.history.getBackUrl()) & '"'>
<cfoutput>
function back() {
window.location = #variables.stWindowLocation#;}
</cfoutput>