Dynamic Templates in AngularJS - javascript

Assume data like
var data = {
name: {type: 'text', label: 'Name'},
age: {type: 'select', label: 'Your age',
options: ['< 18', '18 - 63', '> 63']},
country: {type: 'select', label: 'Where are you from',
options: {de: 'Germany', 'it': 'Italy'}}
}
and many more types.
How do I render this using AngularsJS? ng-switch would be possible but I dont want to "hardcode" all cases. I'm looking for some kind of dynamic directive.
<form>
<div ng-repeat="element in elements">
<label>{{element.label}}</label>
<form-element data="element" />
</div>
</form>
Result:
<form>
<div>
<label>Your name</label>
<input name="name" type="text" />
</div>
<div>
<label>Your age</label>
<select name="age">
<option><18</option>
<option>18-63</option>
<option>>63</option>
</select>
</div>
<div>
<label>Where are your from</label>
<select name="country">
<option value="de">Germany</option>
<option value="it">Italy</option>
</select>
</div>
</form>
Using a function as templatePath does not help because it has no access to the scope.

Related

Create many forms with loop

Hello I am trying to create several forms from a loop that comes from dynamic elements loaded from the database. However I think I am doing it wrong here is what I have already done. It works more or less but I would like to have the right way to proceed.
Thanks in advance
submitForm: function (e) {
e.preventDefault();
e.target.elements.techId.value // OK
this.selectUser // value is other form not form used button
}
Template
<div v-for="tech in techs" :key="tech.id" class="col-12 col-lg-3">
<h3>{{ tech.name }}</h3>
<form
name="form_tech"
method="POST"
#submit="submitForm"
>
<input type="hidden" :value="tech.id" name="techId" id="techId" />
<select
name="select_user"
class="form-select"
v-model="selectUser"
>
<option value="user_one">user one</option>
<option value="user_two">user two</option>
</select>
<button type="submit" >
Confirm
</button>
</form>
Maybe like following snippet:
const app = Vue.createApp({
data() {
return {
techs: [{id: 0, name: 'aa'}, {id: 1, name: 'bb'}, {id: 3, name: 'cc'}],
selectUser: []
};
},
methods: {
submitForm(id) {
console.log(this.selectUser[id])
}
}
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<div v-for="tech in techs" :key="tech.id" class="col-12 col-lg-3">
<h3>{{ tech.name }}</h3>
<form name="form_tech" method="POST"
#submit.prevent="submitForm(tech.id)"
>
<input type="hidden" :value="tech.id" name="techId" id="techId" />
<select name="select_user" class="form-select"
v-model="selectUser[tech.id]"
>
<option value="user_one">user one</option>
<option value="user_two">user two</option>
</select>
<button type="submit">Confirm</button>
</form>
</div>
</div>

Semantic UI Form validation not working

I'm pretty new to Semantic UI and I'm a little rusty on my Javascript so please bear with me. I literally just copy pasted the code from the Semantic UI example on their website to see how their form validation works and for some reason it's not working with me. Could there be something I'm missing?
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href = "https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css">
<link rel="stylesheet" type="text/css" href = "https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.10/components/form.css">
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"> </script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.10/semantic.min.js"> </script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.10/components/form.js"> </script>
</head>
<body>
<script>
$('.ui.form')
.form({
fields: {
name: {
identifier: 'name',
rules: [
{
type : 'empty',
prompt : 'Please enter your name'
}
]
},
skills: {
identifier: 'skills',
rules: [
{
type : 'minCount[2]',
prompt : 'Please select at least two skills'
}
]
},
gender: {
identifier: 'gender',
rules: [
{
type : 'empty',
prompt : 'Please select a gender'
}
]
},
username: {
identifier: 'username',
rules: [
{
type : 'empty',
prompt : 'Please enter a username'
}
]
},
password: {
identifier: 'password',
rules: [
{
type : 'empty',
prompt : 'Please enter a password'
},
{
type : 'minLength[6]',
prompt : 'Your password must be at least {ruleValue} characters'
}
]
},
terms: {
identifier: 'terms',
rules: [
{
type : 'checked',
prompt : 'You must agree to the terms and conditions'
}
]
}
}
})
;
</script>
<form class="ui form segment">
<p>Tell Us About Yourself</p>
<div class="two fields">
<div class="field">
<label>Name</label>
<input placeholder="First Name" name="name" type="text">
</div>
<div class="field">
<label>Gender</label>
<select class="ui dropdown" name="gender">
<option value="">Gender</option>
<option value="male">Male</option>
<option value="female">Female</option>
</select>
</div>
</div>
<div class="two fields">
<div class="field">
<label>Username</label>
<input placeholder="Username" name="username" type="text">
</div>
<div class="field">
<label>Password</label>
<input type="password" name="password">
</div>
</div>
<div class="field">
<label>Skills</label>
<select name="skills" multiple="" class="ui dropdown">
<option value="">Select Skills</option>
<option value="css">CSS</option>
<option value="html">HTML</option>
<option value="javascript">Javascript</option>
<option value="design">Graphic Design</option>
<option value="plumbing">Plumbing</option>
<option value="mech">Mechanical Engineering</option>
<option value="repair">Kitchen Repair</option>
</select>
</div>
<div class="inline field">
<div class="ui checkbox">
<input type="checkbox" name="terms">
<label>I agree to the terms and conditions</label>
</div>
</div>
<div class="ui blue submit button">Submit</div>
<div class="ui error message"></div>
</form>
</body>
</html>
$(document).ready(function(){
// and here your code
});
as semantic needs jQuery to work so you have to call the semantic UI functions in jQuery.
I was wondering about the answer of Ashish sah. So I created a Code Pen for your problem:
CodePen
This shows that the script must not be in $(document).ready(..
Strange is also that the code from the question works.
Only difference I see: Code Pen adds the Script dependency add the end of the body - not the head.

Angular ng-repeat with mixed elements

I'm trying to convert a form that is using .Net MVC to using Angular. I'm trying to use ng-repeat to produce the input fields within the form. Which this is working as expected. But, I need select fields mixed in with the text input fields.
How do I go about mixing text fields and select fields within one form using ng-repeat? Is it even possible? I'm new to Angular as well. This code is just a very quick example and will be cleaned up and properly structured.
<div ng-app>
<div ng-init="profiles = [
{id: 'first-name', label: 'First Name', type: 'text'},
{id: 'middle-name', label: 'Middle Name', type: 'text'},
{id: 'last-name', label: 'Last Address', type: 'text'},
{id: 'suffix', label: 'Suffix', type: 'text'},
{id: 'social-security-number', label: 'Social Security Number', type: 'text'},
{id: 'DateOfBirth1', label: 'Date of Birth', class: 'datePicker hasDatepicker valid', type: 'text'},
{id: 'years-in-school', label: 'Years in School', type: 'text'},
{id: 'marital-status', label: 'Marital Status', type: 'select'}
]">
<h2>Borrowers Information</h2>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<div ng-repeat="profile in profiles" class="control-group col-md-3">
<label class="control-label" for="{{profile.id}}">{{profile.label}}</label>
<div class="controls">
<input data-val="true" data-val-required="Please enter a valid first name." id="{{profile.id}}" name="{{profile.id}}" value="" type="{{profile.type}}" class="{{profile.class}}">
</div>
</div>
</div>
</div>
<script>
You can use the angular ng-switch or ng-if for the type and add your select options as an array in your form object like this:
https://jsfiddle.net/82u6gj26/
Angular
vm.person = {};
vm.form = [{
type:'text',
label:'First Name',
id:'first_name'
},
{
type:'select',
label:'Marital Status',
id:'marital_status',
options:[
{id:'Single',name:'Single'},
{id:'Married',name:'Married'}
]}
];
HTML
<div ng-repeat="form in ctrl.form">
<div class="form-group">
<label>{{form.label}}</label>
<div ng-switch="form.type">
<input
type="text"
ng-switch-when="text"
ng-model="ctrl.person[form.id]">
<select
ng-switch-when="select"
ng-model="ctrl.person[form.id]"
ng-options="s.id as s.name for s in form.options">
<option>Select One</option>
</select>
</div>
</div>
</div>
You can use ng-if directive (https://docs.angularjs.org/api/ng/directive/ngIf).
For example:
...
<div class="controls">
<input ng-if="profile.type != 'select'">
<select ng-if="profile.type == 'select'">
</select>
</div>
...
yes this possible,
<div ng-repeat="profile in profiles" class="control-group col-md-3">
<label class="control-label" for="{{profile.id}}">{{profile.label}}</label>
<div class="controls">
<input data-val="true" data-val-required="Please enter a valid first name." id="{{profile.id}}" name="{{profile.id}}" value="" type="{{profile.type}}" class="{{profile.class}}" ng-if="{{profile.type!='select'}}">
<select id="{{profile.id}}" name="{{profile.id}}" class="{{profile.class}}" ng-if="{{profile.type=='select'}}">
<option value="{{option.value}}" ng-repeat="option in profile.options">{{option.caption}}</option>
</select>
</div>
</div>
</div>
use ng-if or ng-show to which element to display

comparing values from two different context using mustache and canjs

Lets say I have this mustache template below. contacts and categories are basically an array of objects:
<script type="text/mustache" id="contactsList">
<ul class="clearfix">
{{#contacts}}
<li class="contact span8">
<i class="icon-remove"></i>
<form>
<div class="row">
<div class="span2">
<img src="img/canjs.jpg" width="100" height="100">
</div>
<div class="span3">
<input type="text" name="name" placeholder="Add Name" value="{{name}}">
<select name="category">
{{#categories}}
<option value="{{data}}" {{sameCategory category data}}>
{{name}}
</option>
{{/categories}}
</select>
</div>
<div class="span3">
<label>Address</label>
<input type="text" name="address" value="{{address}}">
<label>Phone</label>
<input type="text" name="phone" value="{{phone}}">
<label>Email</label>
<input type="text" name="email" value="{{email}}">
</div>
</div>
</form>
</li>
{{/contacts}}
</ul>
</script>
What I want to do is generate "selected" within the option tag by comparing the contacts|category and categories|data.
so what I did was to implement the sameCategory like this:
can.Mustache.registerHelper('sameCategory', function(contactCategoryId, categoryId) {
console.log(contactCategoryId);
console.log(categoryId);
var result = contactCategoryId == categoryId ? "selected" : "";
console.log(result);
return result;
});
Unfortunately, im getting an object for both param instead of strings so my equality condition fails. What am I doing wrong? is there a better way to do this besides registerhelper?
supporting data:
var CONTACTS = [
{
id: 1,
name: 'William',
address: '1 CanJS Way',
email: 'william#husker.com',
phone: '0123456789',
category: 'co-workers'
},
{
id: 2,
name: 'Laura',
address: '1 CanJS Way',
email: 'laura#starbuck.com',
phone: '0123456789',
category: 'friends'
},
{
id: 3,
name: 'Lee',
address: '1 CanJS Way',
email: 'lee#apollo.com',
phone: '0123456789',
category: 'family'
}
];
var CATEGORIES = [
{
id: 1,
name: 'Family',
data: 'family'
},
{
id: 2,
name: 'Friends',
data: 'friends'
},
{
id: 3,
name: 'Co-workers',
data: 'co-workers'
}
];
I took these code from the examples Diving into CanJS article.
I was checking out your code on a fiddle, and I couldn't replicate it, though perhaps you were getting can.computes that you would need to run as function before you got the values.
However, that said, the helper is entirely unnecessary with the can/view/bindings plugin. Just set can-value="category" on your select and it will auto-magically select the correct option (and update the value when changed).
Demonstrated in a fiddle: http://jsfiddle.net/air_hadoken/g725X/1/
<select name="category" can-value="category">
{{#categories}}
<option value="{{data}}" >
{{name}}
</option>
{{/categories}}
</select>

Knockout.js: Combining javascript objects and select options

In knockoutjs, I want to implement the following: The user can select one of the predefined courses and enter the amount of sessions. The system then displays the total price (amount of sessions multiplied by the price per session for the selected course). I'm still new to knockoutjs so I'm still trying to figure out a lot of things.
So in my program I tried binding an array of javascript objects to select options, but I couldn't find any way to receive the selected object. How can I make the code below work as described? Thanks.
<script type="text/javascript">
// <![CDATA[
$(function() {
var myViewModel = function() {
this.aCourses = ko.observableArray([
{value: 'course_1', text: 'Course 1', price: 35},
{value: 'course_2', text: 'Course 2', price: 39},
{value: 'course_3', text: 'Course 3', price: 30},
{value: 'course_4', text: 'Course 4', price: 43},
]);
this.sSelectedCourse = ko.observable();
this.iSessionCount = ko.observable(0);
this.fTotalPrice = ko.computed(function() { return this.sSelectedCourse().price * this.iSessionCount; }, this);
};
ko.applyBindings(myViewModel);
});
// ]]>
</script>
<div class="main-column-container">
<form class="form-horizontal" role="form" method="post">
<div class="form-group">
<label for="cursus" class="control-label col-sm-3">Rijopleiding</label>
<div class="col-sm-9">
<select class="form-control" id="cursus" name="cursus" data-bind="
options: aCourses,
optionsText: 'text',
value: sSelectedCourse,
optionsCaption: 'Selecteer...'">
</select>
</div>
</div>
<div class="form-group">
<label for="session_count" class="control-label col-sm-3">Amount</label>
<div class="col-sm-9">
<input class="form-control" id="session_count" name="session_count"
data-bind="value: iSessionCount" />
</div>
</div>
<div class="form-group">
<label for="price_total" class="control-label col-sm-3">Total</label>
<div class="col-sm-9">
<p class="form-control-static" data-bind="text: fTotalPrice"></p>
</div>
</div>
</form>
</div>
Conceptually your code is fine, but you have some bugs in your fTotalPrice function: It does not take in account when sSelectedCourse is uninitialized (as it is when the page loads),
and iSessionCount is a function, so it needs to be executed for your calculation to work. An example that should work (not tested):
this.fTotalPrice = ko.computed(function() {
var selectedCourse = this.sSelectedCourse();
return (selectedCourse ? selectedCourse.price : 0) * this.iSessionCount();
},
this);

Categories

Resources