Overriding template logic in TowerJS Views - towerjs

How do I override how templates are rendered in TowerJS? I know I can use Jade, but if I stuck with CoffeeKup, how could I, for instance have this code:
formFor #user, (form) ->
form.fieldset "Profile", (fields) ->
fields.field "firstName"
fields.field "lastName"
fields.field "email"
form.fieldset "Address", (fields) ->
fields.field "lat", as: hidden
fields.field "lng", as: hidden
fields.field "street"
fields.field "city", as: "select", collection: ["CA"]
... generate this:
<form class='form' data-method='post' method='post' novalidate='true' role='form'>
<fieldset class='fieldset' id='profile'>
<legend class='legend'>
<span>Profile</span>
</legend>
<li class='field-list'>
<li class='field string optional validate'>
<label class='label' for='active-record-user-first-name-input'>
<span>First Name</span>
...instead of this:
<form class='form' data-method='post' method='post' novalidate='true' role='form'>
<fieldset class='fieldset' id='profile'>
<legend class='legend'>
<span>Profile</span>
</legend>
<ol class='field-list'>
<li class='field string optional validate'>
<label class='label' for='active-record-user-first-name-input'>
<span>First Name</span>
I guess I'm nitpicking over the <ol> versus <ul>, but I am just starting use Tower in evaluation to Railway and Derby. Is this a CoffeKup question or Mint question?

You can customize that tag by setting:
Tower.View.fieldListTag = 'ul' # or whatever
The configuration variables are here:
https://github.com/viatropos/tower/tree/master/packages/tower-view/shared/view.coffee#L16-92

Related

Can't select chechbox with v-model in VueJS

I have a checkbox as a feature filter for a real estate agency site.
From the database comes the list of categories with their respective characteristics:
public function get_categories(Request $request)
{
$categories = Category::with('features')->get();
return response()->json([
'validation' => true,
'categories' => $categories
]);
}
In the Vue template, I have an accordion with UIKit.
I have one accordion header per category that I walk through using a v-for
Then inside the body of the accordion I have the checkboxes that correspond to the characteristics that belong to that category
<li
v-for="category in categories"
:key="category.id">
<a
href="#"
class="uk-accordion-title">
{{ category.name }}
</a>
<div class="uk-accordion-content">
<div uk-grid>
<div
class="uk-width-1-1 uk-margin-small"
v-for="feature in category.features"
:key="feature.id">
<label>
<input
:id="'feature_' + feature.id"
class="uk-checkbox"
type="checkbox"
name="features"
:value="feature.id"
v-model="features"
#change="filterUpdate"> <!-- ID hacer que este sea venga de la BD -->
{{ feature.name }}
</label>
</div>
</div>
</div>
</li>
To load the categories of course I have a method that is responsible for making the request when creating the component
layoutLoadCategories() {
axios.get('api/layout/get/categories').then( res => {
this.categories = res.data.categories;
});
},
The problem is that when I try to click on a checkbox, nothing happens. Not selected
When you are using v-model you no need to use :value and moreover since its a checkbox input you v-model variable should hold only boolean value (ie) either true or false
<input
:id="'feature_' + feature.id"
class="uk-checkbox"
type="checkbox"
name="features"
v-model="features" // here I guess features is an object or array...so assign a variable that is of type Boolean
#change="filterUpdate">
I have already worked out, in the form tag I had # click.prevent
I have removed the .prevent and it already works
Before:
<form id="filter_form" action="/property-browser" method="get" #click.prevent="filterUpdate">
After:
<form id="filter_form" action="/property-browser" method="get" #click="filterUpdate">

Razor tag helper bool Radio buttons clientside 'Required' validation

I am using Razor Pages Tag helpers for a Yes/No in a form on a page. All other fields in the form have client side unobtrusive validation, but the bool? Yes/No does not. I have a few radio Yes/No's like this, how do I get the client side to work for them?
[Required]
public bool? Have7DaysWorth { get; set; }
I tried moving away from tag helpers too, butit doesn't hook up with this:
<label asp-for="Have7DaysWorth" class="control-label"></label>
<div>
<input type="radio" id="daysRadio1" name="Have7DaysWorth "
checked="#(Have7DaysWorth == true ? "checked": null)"
class="custom-control-input" value="true">
<label class="custom-control-label" for="daysRadio1">Yes</label>
</div>
<div>
<input type="radio" id="pharmacyRadio2" name="Have7DaysWorth "
checked="#(Have7DaysWorth == false ? "checked": null)"
class="custom-control-input" value="false">
<label class="custom-control-label" for="daysRadio1">No</label>
</div>
<span asp-validation-for="Have7DaysWorth " class="text-danger"></span>
I know from searching there are some suggestions about pre-selecting one, but that isn't then a conscious value that a user has entered into a form, so not an option here.
I have tried some other ways, but they seemed to lose the value when the modelstate wasn't valid and was returned.
How do I get the client side to work for bool radios in the expected way that I want?
You're not using asp-for on the radios, so it has no idea it should be required, as there's no involvement with the model, and thus the Required attribute on that property.
An old thread but if you're having to upgrade a razor page website to Bootstrap 5 you'll run into this issue.
This will not work as you cannot use asp-for with C# statement not inside an attribute
<input asp-for="MarketingPrefs" type="radio" class="btn-check" value="true" #(Model.MarketingPrefs.HasValue && Model.MarketingPrefs.Value ? "checked" : null)>
If you omit the asp-for like this then local validation won't work
<input id="MarketingPrefsYes" name="MarketingPrefs" type="radio" class="btn-check" value="true" #(Model.MarketingPrefs.HasValue && Model.MarketingPrefs.Value ? "checked" : null)>
This is how to do it
<div class="btn-group" role="group">
#Html.RadioButtonFor(model => model.MarketingPrefs, "true", new { #class = "btn-check", #id="MarketingPrefsYes" })
<label class="btn btn-outline-secondary" for="MarketingPrefsYes">Yes</label>
#Html.RadioButtonFor(model => model.MarketingPrefs, "false", new { #class = "btn-check", #id="MarketingPrefsNo" })
<label class="btn btn-outline-secondary" for="MarketingPrefsNo">No</label>
</div>

Form containing with ViewComponent

I couldn't figure out how to use ViewComponent inside form
The form is rendered correctly (value in the dropdown), but the model binding, when posting form, fail
This is the view
<form asp-action="" method="post">
<div asp-validation-summary="All"></div>
<div class="row">
<vc:periodi model="#(Model.Periodi)"></vc:periodi>
</div>
This is the ViewComponent
<div class="col-2">
#(Html.Kendo().DropDownListFor(a => a.Anno)
.DataTextField("Text")
.DataValueField("Value")
.BindTo(Model.Anni)
.HtmlAttributes(new { style = "width: 100%" }))
No matter what I choose in the dropdown, the variable Anno inside the Object Periodi of the Model is null
I checked the rendered HTML
<input id="Anno" name="Anno" ...
I think, based on my experience with MVC, that should be something like "Periodi.Anno" for the model binder to work.
Any suggestion?
As your experience, the name should be Periodi.Anno to bind the ViewComponent property.
As my test with input tag like below:
<input asp-for="Name" name="MVCSubModel.Name" class="form-control" />
I suggest you try :
#(Html.Kendo().DropDownListFor(a => a.Anno)
.DataTextField("Text")
.DataValueField("Value")
.BindTo(Model.Anni)
.HtmlAttributes(new { style = "width: 100%"; name = "Periodi.Anno" }))

Vue js input array for cloneable sections

I have input sections like so:
<div class="cloneable" data-id="0">
<div class="col-md-9">
<div class="form-group">
<label>Skills and Qualifications Titles</label>
<input placeholder="ex : PHP, WordPress" name="skill.name" type="text" class="form-control" vmodel="skill.name">
<span class="help-block text-danger" v-text="errors.get('skill.name')"></span>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label>Skill Level %</label>
<input placeholder="ex : 90" name="skill.percentage" type="text" class="form-control" v-model="skill.percentage">
<span class="help-block text-danger" v-text="errors.get('skill.percentage')"></span>
</div>
</div>
</div>
Each section can be cloned to make a duplicate, so I am trying to array my data so I can access it backend like
skill[0]['name']
skill[1]['name']
skill[2]['name']
... etc
I am initiating the data like so:
skill: [
{
'name': '',
'percentage': ''
}
],
I have tried using the models like skill.index.name, but that doesn't work, how can I achieve what I am trying to do above?
If I understand, you have an array of skills like:
skill: [
{'name': 'a_name', 'percentage': '20'}
{'name': 'b_name', 'percentage': '30'}
],
and you want to access a particular member of that array in your template. The normal way the arrays end up in templates is using a v-for: like:
<li v-for="a_skill in skill">
{{ a_skill.name }}
</li>
…which would like all the skills in the array.
If you want to access a particular member of that array you will need to add the index like this:
<input v-model="skill[0].name"> // not skill.0.name
(don't forget the hyphen in v-model it's missing in your example)
You can even do that if you have some data you want to use as the index. For example:
data () {
return {
skill: [
{"name": "Foo"},
{"name": "Bar"}
],
i: 1
}},
Then you could use this in your template:
<input v-model="skill[i].name">

Working with multiple html helpers of same name in mvc4

I have multiple html helpers. When I click login button I am disabling user_register div using jquery and when I enter details the username and password the model binder is able to bind properly but when I click Register I am disabling user_login div and enabling user_register div and when I enter the details only email and firstname is what the model binder is able to bind and not username, password. Is this becoz I am using the same html helpers more than once. How to handle this. I have the following code
<div class="user_login">
<label>Email / Username</label>
#Html.TextBoxFor(model => model.Email)
<br />
<label>Password</label>
#Html.TextBoxFor(model => model.Password)
<br />
<div class="action_btns">
<div class="one_half"><i class="fa fa-angle-double-left"></i>Back
</div>
<div class="one_half last">
<input type="submit" style="border: none" name="action" class="btn btn_red" value="Login" />
</div>
</div>
Forgot password?
</div>
<div class="user_register">
<label>Full Name</label>
#Html.TextBoxFor(model => model.First_Name)<br />
<label>Email Address</label>
#Html.TextBox(model=>model.Email)<br />
<label>User Name</label>
#Html.TextBoxFor(model => model.User_Name)<br />
<label>Password</label>
#Html.TextBox(model=>model.Password") <br />
</div>
The controller follows here
public ActionResult Index(Customer customer, string Action)
{
//something here
}
You have not shown you complete view, but assuming all those controls are generated inside one form element, then all controls will post back unless you make the inputs disabled. If so, then the first input with name="Email" is bound and the second one is ignored by the DefaultModelBinder. (since the first one is only hidden, its value is probably empty). Your script needs to ensure that the 2 inputs in the login section are disabled, for example
#Html.TextBoxFor(model => model.Email, new { id = "login-email" })
and
$('#login-email').prop('disabled', true);
Note the id attribute so you can select the correct one (and prevent duplicate id's which is invalid html.
An alternative would be to create 2 separate forms.