AngularJS - Radio buttons in a loop? - asp.net-mvc

We are using ASP.NET MVC and AngularJS (Newbie on Angular) and I'm really stuck with bloated html.
I have a bunch of radio button choices that are true/false but are bound to a nullable (bool?)
This works below just fine, but it's a lot of repeating code. Can it be shrunk using the wonders of Angular? (We're going to have a lot of these kinds of yes/no/no choice controls)
<div class="rdio rdio-primary col-xs-4 col-sm-4 col-md-2 col-lg-3">
<input type="radio"
name="#(Html.NameFor(x => x.IsUSAResident))"
id="resTrue"
ng-value="true"
required
ng-model="model.IsUSAResident">
<label for="resTrue" class="pull-left">Yes</label>
</div>
<div class="rdio rdio-primary col-xs-4 col-sm-4 col-md-2 col-lg-3">
<input type="radio"
name="#(Html.NameFor(x => x.IsUSAResident))"
id="resFalse"
ng-value="false"
required
ng-model="model.IsUSAResident">
<label for="resFalse" class="pull-left">No</label>
</div>

Yes, you can shrink it using ng-repeat:
<div ng-init="options = [{id:'resTrue',value:true,label:'Yes'},{id:'resFalse',value:false,label:'No'}]">
<div ng-repeat="option in options"
class="rdio rdio-primary col-xs-4 col-sm-4 col-md-2 col-lg-3">
<input type="radio"
name="#(Html.NameFor(x => x.IsUSAResident))"
id="{{option.id}}"
ng-value="option.value"
required
ng-model="model.IsUSAResident">
<label for="{{option.id}}" class="pull-left">{{option.label}}</label>
</div>
</div>
There are ways to improve this code further. One would be to create a controller to hold the options (to get rid of ng-init):
angular.module('myApp')
.controller('yesNoRadioCtrl',function($scope){
$scope.options = [
{id:'resTrue', value:true, label: 'Yes'},
{id:'resFalse', value:false, label: 'No'}
];
});
The corresponding markup:
<div ng-controller="yesNoRadioCtrl">
<div ng-repeat="option in options"
class="rdio rdio-primary col-xs-4 col-sm-4 col-md-2 col-lg-3">
<input type="radio"
name="#(Html.NameFor(x => x.IsUSAResident))"
id="{{option.id}}"
ng-value="option.value"
required
ng-model="model.IsUSAResident">
<label for="{{option.id}}" class="pull-left">{{option.label}}</label>
</div>
</div>
This can be made more compact and reusable with directives. Let me know if you'd like to see that.

Jonathan is right. You can save some space, with just ng-repeat'ing your radio-inputs.
Here's how you could create your own directive and implement some more radio inputs, with much smaller code:
ยป Demo on plunker
JS
angular.module('foobar', [])
.controller('Controller', ['$scope', function($scope) {
$scope.zuzu = "a value";
$scope.bars = [
{id:"one"},
{id:"two"},
{id:"three"}
];
for(i=0;i<$scope.bars.length;i++) {
$scope.bars[i]["name"] = 'just-a-radio-group';
}
}])
.directive('myRadio', function() {
return {
restrict: 'E',
scope: {
data: '=',
ngModel: '=ngModel'
},
templateUrl: 'template.html'
};
});
HTML (index.html)
<body ng-app="foobar">
<div ng-controller="Controller">
<h3>{{zuzu}}</h3>
<!-- they won't update the scope -->
<my-radio ng-repeat="bar in bars" ng-model="zuzu" data="bar"></my-radio>
<!-- they will update the scope -->
<my-radio ng-model="zuzu" data="bars[0]"></my-radio>
<my-radio ng-model="zuzu" data="bars[1]"></my-radio>
<my-radio ng-model="zuzu" data="bars[2]"></my-radio>
</div>
</body>
HTML (template.html)
<div class="rdio rdio-primary col-xs-4 col-sm-4 col-md-2 col-lg-3">
<input type="radio"
name="data.name"
id="data.id"
ng-value="data.id"
required
ng-model="ngModel">
<label for="data.name"
class="pull-left"
>
{{data.id}}
</label>
</div>
Additional note, why ng-repeating the custom-directive won't update ng-model:
https://github.com/angular/angular.js/issues/1913

Related

Devise params auto adds weird data in sign up registration controller

My application using vue3 to build devise sign up page and i'm using axios request to create user.
In registration controller, i found that params has added added an extra field name called registration data.
<ActionController::Parameters {"user"=>{"name"=>"name", "email"=>"mail", "phone"=>"123", "type"=>0}, "controller"=>"users/registrations", "action"=>"create", "registration"=>{"user"=>{"name"=>"name", "email"=>"mail", "phone"=>"123", "type"=>0}}}
It contains params[:user], that looks weird to me. Can someone explain?
"registration"=>{"user"=>{"name"=>"name", "email"=>"mail", "phone"=>"123", "type"=>0}
My form code:
methods: {
signUp: function(e) {
e.preventDefault();
let user_params = {
user: {
name: this.name,
email: this.email,
phone: this.phone,
type: this.type,
}
}
this.$http.post('/users', user_params)
.then(response => {
this.$emit('next');
}).catch(err => {
this.error = err.response.data;
});
},
}
And in view
<form>
<div class="col-md-6 col-sm-8 col-10 mt-5 mx-auto text-center">
<div class="checked-circle mx-auto">
<img :src="checkedStepImg" class="w-100 h-100">
</div>
<div class="title mt-5"> Let sign up for your account </div>
<div class="mt-3 text-red" v-if="error">{{ error }} </div>
<div class="row mt-3">
<div class="col-6">
<input class="form-control shadow-none rounded-0" placeholder="Name" v-model="name">
</div>
<div class="col-6">
<input class="form-control shadow-none rounded-0" placeholder="Email" v-model="email">
</div>
</div>
<div class="row mt-3">
<div class="col-6">
<div class="input-group">
<span class="input-group-text rounded-0">+1</span>
<input type="text" class="form-control shadow-none rounded-0 bg-white" placeholder="Phone" v-model="phone">
</div>
</div>
<div class="col-6">
<select class="form-select shadow-none rounded-0" aria-label="Default select example" v-model="type">
<option value="0" selected> Personal </option>
<option value="1"> Corporation </option>
</select>
</div>
</div>
<div class="col-6 col-sm-5 mx-auto btn-box mt-5">
<button class="btn btn-dark w-100 h-100" #click.prevent="signUp"> Sign up!</button>
</div>
</div>
</form>
That does not happen if i use a normal form devise sign_up

Angular 7 Reactive Form returns previous entered value on Pressing Enter key

I have created a login form using angular reactive form. I've facing some strange behavior
If I submit the form using the submit button, I get the latest values which I've entered. If I submit the form using Enter key, then the value received is not latest. I've added the code below, can anyone pls suggest what i'm doing wrong.
ngOnInit() {
this.loginForm = this.formBuilder.group(
{
username: new FormControl(),
password: new FormControl(),
RememberMe: []
},
{
updateOn: 'blur'
}
);
}
login() {
const formvalue = this.loginForm.value;
console.log(formvalue);
return;
}
<div class="limiter">
<div class="container-login100 img-bg">
<div class="wrap-login100">
<img class="logo-center" src="../../../../assets/images/logo-big.png" />
<form [formGroup]="loginForm">
<div class="ui segment">
<h2>Login Form</h2>
<div class="ui form" >
<div class="required inline field">
<label>Username</label>
<div class="ui left icon input">
<i class="user icon"></i>
<input type="text" name="Username" placeholder="username" formControlName="username" >
</div>
</div>
<div class="required inline field">
<label>Password</label>
<div class="ui left icon input">
<i class="lock icon"></i>
<input [type]= "'password'" placeholder="password" formControlName="password" >
</div>
</div>
<div class="field login-ckeck">
<sui-checkbox>
Remember me
</sui-checkbox>
</div>
<button [ngClass]= "'ui primary button'" (click)= "login()">Submit</button> Forgot your password?
</div>
</div>
</form>
</div>
<!-- <footer class="footer">footer</footer> -->
</div>
</div>
Found the solution, it was an error from my side.
I had to change the updateOn to submit, for my code to work
this.loginForm = this.formBuilder.group(
{
username: new FormControl(),
password: new FormControl(),
RememberMe: []
},
{
updateOn: 'submit'
}
);
You can listen to either the forms (ngSubmit) or directly to the (keyup.enter) event and trigger the event then.
<form (ngSubmit)="login()">
<form (keyup.enter)="login()">

ReactJS.NET : Unable to get click events to fire

I'm running ReactJS.NET with ASP.NET MVC, and everything renders well, except... i cannot get any kind of events to fire...
What i have tried :
1) Eliminating all JQuery references/usages - no success
2) onHover, onClick, with functions both inside and outside of the React-component - no success
Here is my code :
Attaching ProductLine React component in index.cshtml
#Html.React("ProductLine", Model)
React component
function addToCart() {
alert("Hoohohoho!!!");
};
var ProductLine = React.createClass({
render: function () {
return(
<div className="col-md-12 col-sm-12 col-xs-12" key={this.props.productData.name}>
<button onClick={this.addToCart}>Click me!</button>
<div className="row" >
<div onClick={addToCart} className="col-md-12 col-sm-12 col-xs-12 nopadding row-default" >
<div className="col-md-3 col-sm-5 col-xs-5 nopadding">
<span className="table table-col ">
<input type="checkbox" id="cbxCheck2" className="jq_select_product" />
<label htmlFor="cbxCheck2" className="jq_select_product">{ this.props.productData.name }</label>
</span>
</div>
<div className="col-md-4 hidden-sm hidden-xs nopadding">
<span className="table table-col table-text-small">
{ this.props.productData.label }
</span>
</div>
<div className="col-md-3 col-sm-4 col-xs-4 nopadding">
<span className="table table-col">
849,- (12 mnd)
</span>
</div>
<div className="col-md-2 col-sm-3 col-xs-3 nopadding">
<span className="table table-col table-text-small text-right">
<img id="imgShowMore" src="../../Images/arrow_purple_down.png" className="show-more _icon jq_expand_listview" /><label className="show-more _lbl jq_expand_listview">Vis mer</label>
</span>
</div>
</div>
<ProductDetails productData={this.props.productData} />
</div>
</div>
);
},
addToCart: function (e) {
alert("Hooooo!!!");
},
});
After 1/2 a day of trial and error, i suddenly tried to put all the JSX file references at the bottom of the _Layout.cshtml page...
That solved it all actually...

Form validations lost when included in template

I have a directive, which successfully includes a template in my AngularJS app using Rails 4.2 and angular-rails-templates.
Everything seems to be working fine, even the two way data binding, although there is one exception. Form validation using AngularJS is lost if I include the <form> tag inside the template file.
When I run this in my local environment, Angular includes the template, display it on my main page. if you enter data the two way data binding updates, but the form validation is not handled by Angular, it uses HTML5 browser validation instead.
Any help appreciated, I assume there is some common thing I am missing, like how / when the template is inserted?
I have prepared a working demo at Plnkr, the same code executes without incident on Plnkr, but not when using Rails.
JS:
var app = angular.module('app', ['templates']);
app.config([
'$httpProvider', function($httpProvider) {
return $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');
}
]);
app.run(function() {
return console.log('angular app running');
});
app.directive('serviceRequest', function() {
return {
restrict: 'E',
templateUrl: 'service-request.html',
controller:function() {
this.request = {};
this.addService = function(request) {
//$http request
this.request = {};
}
},
controllerAs: 'service'
};
});
The HTML template (service-request.html):
<form name="myForm" novalidate="">
<div>
serviceForm is {{myForm.$valid}}
</div>
<fieldset>
<legend>Service Request</legend>
<h1>{{service.request.number}} <small>{{service.request.reported | date}}</small></h1>
<div class="row">
<div class="small-12 medium-10 large-10 small-centered">
<div class="row">
<div class="small-3 columns">
<label for="right-label" class="right">Number:</label>
</div>
<div class="small-9 columns">
<label>
<input type="text" ng-model="service.request.number" placeholder="small-9.columns" required/>
</label>
</div>
</div>
</div>
</div>
<div class="row">
<div class="small-12 medium-10 large-10 small-centered">
<div class="row">
<div class="small-3 columns">
<label for="right-label" class="right">Reported:</label>
</div>
<div class="small-9 columns">
<input type="text" ng-model="service.request.reported" placeholder="small-9.columns" required/>
</div>
</div>
</div>
</div>
<input type="submit" ng-disabled="myForm.$invalid ">
</fieldset>
</form>

align to right an element in jquery mobile

I've created this elements form:
<div class = "ui-grid-a">
<div class= "ui-block-a">
<div data-role="fieldcontain" class = "ui-hide-label">
<label for="birth-place">Birth Place</label>
<input type="text" name="birth-place" id="birth_place" value="" placeholder="Birth Place" />
</div>
</div>
<div class = "ui-block-b">
<div data-role = "fieldcontain" class="ui-hide-label">
<label for="province">Province</label>
<input type="text" name="province" id="province" value="" placeholder="PR" />
</div>
</div>
</div>
and I want to align the element province to the right. How can I do that?
Try this:
<span style="float:right"><label for="province">Province</label></span>
(of course you can put this also in a external css file)
Just do the following...
Apply this custom CSS to your code...
label[for="province"] { text-align:right; }
If it doesn't run they supply the label with a class name and do the following..
label.className { text-align:right; }
Apply a style of text-align:right;to the input field directly, as in this fiddle.
http://jsfiddle.net/den232/Fw2yA/
Good luck!
.floatright {
text-align:right;
}
<div data-role="page" class="type-home">
<div data-role="content">
<div class = "ui-grid-a">
<div class= "ui-block-a">
<div data-role="fieldcontain" class = "ui-hide-label">
<label for="birth-place">Birth Place</label>
<input type="text" name="birth-place" id="birth_place" value="" placeholder="Birth Place" class='floatright' />
</div>
</div>
<div class = "ui-block-b">
<div data-role = "fieldcontain" class="ui-hide-label">
<label for="province">Province</label>
<input type="text" name="province" id="province" value="" placeholder="PR" />
</div>
</div>
</div>
</div>
</div>

Resources