Concatenating in Razor - html

I am trying a simple concatenation in razor.
I get all kinds of squiqly lines when I add this in my model RAZOR:
<input type="checkbox" id="ck1-#track.TrackID"
onclick="$('#ck2-#(track.TrackID)').prop('checked', $(this).prop('checked'))" />
However it outputs perfectly OUTPUT:
<input type="checkbox"
id="ck1-500004524"
onclick="$('#ck2-500004524').prop('checked', $(this).prop('checked'))">
I am trying to get the exact html as in the output, but without all of the squigly.
I understand this is most likely covered in other posts, but I am still trying to get the grasp on the way Razor concatenates strings, it seems to be different each time I need it.
Thank you in advance,

As mentioned, Razor isn't friendly to injecting variables into html attributes. Part of the reason is that linking event handlers in Mark-up is an outdated practice.
best practice is the "Unobtrusive way"
$(function () {
$('#').click(function ()
{ $('#ck2-#(track.TrackID)').prop('checked', $(this).prop('checked')) })
})

Having #code inside of html/javascript strings e.g "#code" or '#code' will almost always give you squiggly lines.

On lines where I am mixing HTML markup & Razor syntax, I preface the line with a #: which I've found resolves a lot of issues.
Also, check out http://weblogs.asp.net/scottgu/archive/2010/12/16/asp-net-mvc-3-implicit-and-explicit-code-nuggets-with-razor.aspx
This snippet is good advice:
When necessary, you can also explicitly scope code expressions using a
#(expression) syntax to provide greater clarity around your intent, as
well as to disambiguate code statements from static markup.

Thank you for everyone that helped, one of the answers suggested that the 'unobrusive way' would be better than hardcoding javascript into the elements. Here is what I came up with:
<input type="checkbox" class="ckSelectCol" />
$(function () {
$('.ckSelectCol').each(function () {
$(this).change(function () {
dupCheckBox(this);
});
});
});
What this is doing is finding all checkboxes that have a class ckSelectCol and adding a change eventhandler, the change event handler is the function that I wish to be called on change.
This can be done a multitude of ways, I chose this way as it decouples the javascript from the page, can easily be reused and makes the page lighter.
If anyone has any suggestions, please respond.
Once again, I appreciate all of the input that I received on this post.
-Edward

Related

Angular2 function call from html element with no load event (or similiar)

I am new to Angular and have run into a problem that seems to have a javascript work around but they aren't very elegant.
I have a model with an array property. I ngfor the list property to build some html selection options. This is all working nicely. The problem comes when I am trying to set default value...the html elements don't have a load event.
I tried numerous html elements and they don't appear to have a load event either but I certainly could be doing it wrong.
I have seen a solution to put javascript tag right after the html and I could do that but I was really looking for a more elegant way in Angular.
I saw this SO post and thought that was my answer but there is a warning given that I agree with and thus it doesn't appear to be a good solution.
Regardless I tried it just to see if it would work and I got:
Failed to execute 'setAttribute' on 'Element': '{{loadDefaults()}}' is not a valid attribute name
<span {{loadDefaults()}} ></span>
So how can I fire an AS2 function in the component to load the default values?
HTML (btw this is NOT a full page load so there is no body tag):
<tr>
<td *ngFor="let loc of locOptions;">
<span>{{loc.text}}</span>
<input type="radio" name="radiogroup" [value]="loc.value" (change)="onSelectionChange(loc.value)">
</td>
</tr>
Edit
I thought perhaps mistakenly that ngoninit would fire too soon...before the html elements are rendered.
So perhaps what is being suggested is that I add a boolean is default to the model and bind THAT as the element is rendered.
In your ngonit function set this.locOptions to your default values. The value can be changed later on in any function and the change will be reflected in the view. Hope this helps you.
You should use ngOnInit to init you data, and call retrieve your data from your component :
defaults : any;
ngOnInit {
this.defaults = loadDefaults();
}
loadDefaults() {
//get data
}
HTML :
<span>{{defaults}}</span>

Binding dynamically within an ng-repeat expression

For a TV Guide, I am trying to create a dynamic expression within an ng-repeat directive as follows:
<div ng-repeat="programme in programmes['{{channel}}-wed-jan-14']" alt="{{channel}}">
{{channel}} in my controller should evaluate to something like "eTV". The binding is working fine with the alt="{{channel}}" instance but not with the array instance. Angular simply serves up the line of code commented out. If I hardcode the "eTV" string in place of the {{channel}}, it works fine.
Am I trying to ask Angular to do what it is not designed for, or is it possibly my array handling which is dodgy?
Okay, not sure if I just asked a dumb question, but in the absence of responses, I managed to figure out a solution by writing a filter as follows:
Template:
<div ng-repeat="programme in programmes | getChannelDay:channel:dayString" alt="{{channel}}">
Controller filter:
app.filter('getChannelDay', function() {
return function(programmes, channel, dayString) {
return programmes[channel + dayString];
};
});
The issue with my initial problem
<div ng-repeat="programme in programmes['{{channel}}-wed-jan-14']" alt="{{channel}}">
is that I was trying to put {{channel}} inside the expression, but that is the format for markup.
I tried to use the following instead:
<div ng-repeat="programme in programmes['channel + daystring']" alt="{{channel}}">
but I am doing something wrong here. I am pretty sure there is a way to get this to work - if anyone knows, please comment.

Force leading zero in number input

I'm writing an alarm web app. I have two number inputs, one for the hours, one for the minutes. Thus, when I use my keyboard arrows, they go from 0 to 23/59. Is there an HTML native way to make them go from 00 (01,02, et.) to 23/59 instead ?
I'm only worried about the UI aspects as my JS manages the missing 0 anyway.
EDIT - As requested :
What I have :
What I want :
Instead of going from 0,1,2 to 59, I'd like to automatically have a leading 0 when the number is smaller than 10 (00,01,02 to 59).
I use this to just prepend zeros as needed:
<script>
function leadingZeros(input) {
if(!isNaN(input.value) && input.value.length === 1) {
input.value = '0' + input.value;
}
}
</script>
And I just call that on the input's various events how ever works best for me, for instance:
<input type="number"
value="00"
onchange="leadingZeros(this)"
onkeyup="leadingZeros(this)"
onclick="leadingZeros(this)" />
It's not an ideal solution, mainly because there's a slight visual change as the user changes the number and the zero is prepended, but it works for me :)
Edit: Forgot to mention, I appreciate the answer asked for a native solution without javascript, but I wanted to provide something for people landing here through a Google search.
I'm afraid there is not native HTML way to do that unless using a Select tag. If you are using a text input you have to add the leading 0 on the 10 first values by javascript.
The correct, modern solution to OP's problem would be to use a input with type=time and then they don't have to worry about leading zeros or any of this other stuffs.
Adding on to some of the other answers that suggest using an event listener. I've tested this with jquery in chrome and it seems to work well with the padding without the slight flashing side effect.
<input type="number" id="input-element-id" value="00">
<script>
$('#input-element-id').on('input', function() {
const value = $(this).prop('value')
$(this).prop('value', value.padStart(2, '0'))
})
</script>

data-bind: value - parenthesis - observable

I started working with knockout a few months ago and so far it is being a very good road. Today when I was working with some inputs in my html I came across a very boring issue that took me a while to figure out. Here is my code:
<div class="add-box" style="display:none;" id="new-user">
<textarea placeholder="Name" data-bind="value : name"></textarea>
</div>
<script>
function UserViewModel() {
var self = this;
self.name= ko.observable('');
}
$(document).ready(function () {
ko.applyBindings(new UserViewModel(), document.getElementById('new-user'));
})
</script>
This code works fine, but the first time that I did was like this:
<textarea placeholder="Name" data-bind="value : name()"></textarea>
The only difference between them are the parenthesis () at the end of the name property. Since this is a observable one I thought that the parenthesis would be necessary in order to make the 2-way-binding. But with them, whenever I change the value of the textarea the viewmodel is not update accordingly, if I remove everything works.
Could you explain why on this case I have to remove the parenthesis, and why in other scenarios, like when I used data-bind="text: I have to put them??
Here is the magic with KO: special "Observable" function-objects.
When you use parenthesis, you evaluate the observable (which is just a special function) which results in a value that breaks "live" data-binding: in this case the underlying value (say, a string) is bound, but not the observable from which the value was obtained.
The underylying bindings are (usually) smart enough to deal with both observables and non-observable values. However, bindings can only update observables and can only detect Model changes through observables.
So, usually, do not include parenthesis when using obervables with declarative data-binding.
Passing the observable will make sure the Magic Just Works and allow the View and Model to stay in sync. Changes to said bound observable will trigger the appropriate binding update (e.g. so that it can update the HTML) even if the binding does not itself need to update the observable/Model.
However, in some rarer cases, you just want the value right then and you never want the binding to update from/to the Model. In these rarer cases, using parenthesis - to force value extraction and not bind the observable itself - is correct.
In my case I was using jquery.tmpl ,
and knockout 2.2.0 works with jquery.tmpl, when I upgrade to knockout 3.0, I got this problem
when I use this one, It somehow get conflict with Knockoutjs builtin template/
Removing jquery.tmpl.js resolves my problem.

Can I specify maxlength in css?

Can I replace the maxlength attribute with something in CSS?
<input type='text' id="phone_extension" maxlength="4" />
No.
maxlength is for behavior.
CSS is for styling.
That is why.
No. This needs to be done in the HTML. You could set the value with Javascript if you need to though.
You can use jQuery like:
$("input").attr("maxlength", 4)
Here is a demo: http://jsfiddle.net/TmsXG/13/
I don't think you can, and CSS is supposed to describe how the page looks not what it does, so even if you could, it's not really how you should be using it.
Perhaps you should think about using JQuery to apply common functionality to your form components?
Not with CSS, no.
Not with CSS, but you can emulate and extend / customize the desired behavior with JavaScript.
As others have answered, there is no current way to add maxlength directly to a CSS class.
However, this creative solution can achieve what you are looking for.
I have the jQuery in a file named maxLengths.js which I reference in site (site.master for ASP)
run the snippet to see it in action, works well.
jquery, css, html:
$(function () {
$(".maxLenAddress1").keypress(function (event) {
if ($(this).val().length == 5) { /* obv 5 is too small for an address field, just want to use as an example though */
return false;
} else {
return true;
}
});
});
.maxLenAddress1{} /* this is here mostly for intellisense usage, but can be altered if you like */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="text" class="maxLenAddress1" />
The advantage of using this: if it is decided the max length for this type of field needs to be pushed out or in across your entire application you can change it in one spot. Comes in handy for field lengths for things like customer codes, full name fields, email fields, any field common across your application.
Use $("input").attr("maxlength", 4)
if you're using jQuery version < 1.6
and $("input").prop("maxLength", 4)
if you are using jQuery version 1.6+.