comparing values from two different context using mustache and canjs - javascript

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>

Related

How to set value in dropdown while selecting field in jQuery

I would like to dynamically change the options of a HTML dropdown menu based on which customer address city a user selects - for example, I have a JSON data.
addObj
Array(4)
0: {addressee: 'Customer2', country: 'US', state: 'NH', zip: '03103', city: 'Bedford', …}
1: {addressee: 'NB Demo Customer', country: 'US', state: 'MA', zip: '01432', city: 'Devens', …}
2: {addressee: 'Customer1', country: 'US', state: 'MA', zip: '01730', city: 'Bedford', …}
3: {addressee: 'Nb Demo check', country: 'US', state: 'MA', zip: '01748', city: 'Hopkinton', …}
length: 4
[[Prototype]]: Array(0)
and I have image drop down menu.
image 1:
So, here first word before delivery are city names.
another image selecting customer addresses :
image 2:
if the user select any of customer1,customer2,nb demo customer then based on city and state I need to compare and append that particular dropdown in select shipping method.
Likewise, eg: city : Bedford, state : MA then shipping method dropdown should be Beford MA delivery.
I am stuck with a function similar to this one (I am new to web dev and an largely unfamiliar with javascript,Jquery and its syntax):
if (activeAddObj) {
debugger;
if (activeAddObj.city) {
filtered = _.filter(setup.shipping, function(data) {
return data.name === activeAddObj.city + ' ' + 'Delivery';
});
shippingmethod = filtered[0].name;
shippingmethodId = filtered[0].internalId;
console.log('shippingmethod', shippingmethod);
console.log('shippingmethodId', shippingmethodId);
$("#delivery-method-check").prop("checked", true);
$(".delivery-method-container").show();
var delivery = jQuery("#shipping-method");
console.log('delivery', delivery);
var html = "";
if (delivery.html().trim().length <= 0) {
delivery.append($("<option />").val(shippingmethodId).text(shippingmethod));
}
jQuery("#shipping-method").append(html);
}
}
activeAddObj is
address1: "9955"
address2: "9955"
addressee: "NB Demo Customer"
addrsid: "89242"
city: "Devens"
internalid: "89263"
phone: "(987) 987-9870"
state: "MA"
zip: "01432"
[[Prototype]]: Object
setup.shipping is
<div class="shipping-addr-container">
<div class="shipping-addr-div">
<label for="" class="shipping-addr-head"> Ship To</label>
<span class="ship-to-checkbox">
<input type="checkbox" id="ship-to-check" value="" name="update" class="switch_1">
<span class="switch-after"></span>
</span>
<div class="addr-main-container" style="display: none;">
<div class="addr-container">
</div>
</div>
</div>
</div>
<div class="delivery-method-main-container">
<div class="delivery-method-div">
<label for="" class="delivery-method-head">Shipping Method:</label>
<span class="ship-to-checkbox">
<input type="checkbox" id="delivery-method-check" value="" name="update" class="switch_1">
<span class="switch-after"></span>
</span>
<div class="delivery-method-container" style="display: none;">
<div class="select-delivery-method">
<label>Select Shipping method:</label>
<select class="form-control" id="shipping-method">
</select>
</div>
</div>
</div>
</div>
my conclusion is whatever we select any customer address(image 2) based on that city and state we need to compare and select and show dropdown automatically. Please advice me in programming.

Vue.js problem with send values in array to endpoint

I'm just started learning Vue to finish my project. My backend is in Java Spring.
My end-point expect object with values:
LocalDate date;
Long buyerId;
Long supplierId;
List<OrderDetailsDto> orderDetails;
my object in Vue looks like:
order: {
date: '',
buyerId: 0,
supplierId: 0,
orderDetails: [
{
quantity: 0
product: {
id: 0
}
}
]
}
and my inputs for quantity and products (just with those values is problem):
<div class="form-group">
<label>Ilość (m3)</label>
<input type="number" id="quantity" class="form-control" v-model="order.orderDetails.quantity"/>
</div>
<div class="form-group">
<label>Wybierz product</label>
<select v-model="order.orderDetails.product">
<option
v-bind:value="{id: product.id, name: product.product}"
v-for="product in products"
v-bind:key="product.id"
>{{ product.product }}</option>
</select>
</div>
with that settings my request object looks like (that is console.log just before send request):
{__ob__: Observer}
date: (...)
buyerId: (...)
supplierId: (...)
orderDetails: Array(1)
quantity: "22"
product: Object
0:
quantity: 0
product: Object
and here is the problem. Variables which I declared in Vue are at index [0] in orderDetails.
Those values above (quantity: "22", product: Object) are not sent, my end-point thinking that array is empty. If I delete values from array in Vue object, then console.log looks fine but my end-poind doesn't see values in array.
Have anyone idea how to solve that?
add data: {currquantity:0, currproduct: {id: null, name: null}}
<div class="form-group">
<label>Ilość (m3)</label>
<input type="number" id="quantity" class="form-control" v-model="currproduct.quantity"/>
</div>
<div class="form-group">
<label>Wybierz product</label>
<select #change="order.orderDetails.push({quantity: currquantity, ...currproduct})" v-model="currproduct">
<option
v-bind:value="{id: product.id, name: product.product}"
v-for="product in products"
v-bind:key="product.id"
>{{ product.product }}</option>
</select>
</div>
You will probably want to create something like below to handle showing what has been added so far and ability to delete added items:
<ul>
<li v-for="(detail, i) in order.orderDetails">{{JSON.stringify(detail)}}
<button #click="order.orderDetails.splice(i,1)">X</button>
</li>
</ul>

Dynamic Templates in AngularJS

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.

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

Angularjs Populate a select box by selecting two fields in different select boxes

I have 3 select boxes in total. I will select values in 2 select boxes and will click on Submit button. What will be the process to populate the 3rd select box from this. I have data in tables and I am using hibernate in backend. What will be my js file, will the call be post or get. Please help me and give whole procedure.I am using angularjs on frontend side. Please tell me the content of js file as well as the modifications in HTML file. Thank you.
<form name="deviceForm" ng-submit="submitForm()">
<div class="container" style="margin-top:10px">
<div class="row" style="margin-top:20px">
<div class="col-sm-3" align="right">
<h4>Device Family<super style="color:red">*</super></h4>
</div>
<div class="col-sm-2" align="left">
<select class="form-control" ng-model="device.family">
<option>Device 1</option>
<option>Device 2</option>
<option>Device 3</option>
<option>Device 4</option>
<option>Device 5</option>
</select>
</div>
<div class="col-sm-3" align="right">
<h4>Device Type<super style="color:red">*</super></h4>
</div>
<div class="col-sm-2" align="right">
<select class="form-control" ng-model="device.type">
<option>Type 1</option>
<option>Type 2</option>
</select>
</div>
</div>
</div>
<div align="center" style="margin-top:30px">
<button type="submit" value="submit" class="btn btn-info ">Show Devices</button>
</div>
</form>
This is my HTML.
Now after submitting , how would I write in js file to send these Selected options.
With the stinginess of informations you have proved, this is the most I can do:
(() =>
{
'use strict';
angular.module('app', [/**'ng-routing'**/])
.controller('DeviceController', [function ()
{
var self = this;
// self.forms.new
// OR ... angular will handle this for me
// self.forms.edit
self.storage = {}; // to store raw data from service or anywhere, needed for the form initialization
self.storage.types = [{id: 1, label: 'Type 1'}, {id: 2, label: 'Type 2'}, {id: 3, label: 'Type 3'}, {id: 4, label: 'Type 4'}, {id: 5, label: 'Type 5'}];
self.storage.families = [{id: 1, label: 'Device 1'}, {id: 2, label: 'Device 2'}, {id: 3, label: 'Device 3'}, {id: 4, label: 'Device 4'}, {id: 5, label: 'Device 5'}];
self.events = {};
self.events.typeChanged = self.events.familyChanged = function ()
{
self.storage.theThird = undefined; // this will be used to disable submit button while the value is not set, or any service result is waited to set the value
var type = self.data.type || 0;
var family = self.data.family || 0;
if (0 === (type * family) % 2) // you may implement any logic as needed. IF SYNTAX is just an example
{// this code executes only if the `id` at least one of `selected type` or `selected family` is even
self.storage.theThird = [{id: 2, label: '2016-02'}, {id: 4, label: '2016-04'}, {id: 6, label: '2016-06'}, {id: 8, label: '2016-08'}, {id: 10, label: '2016-10'}, {id: 12, label: '2016-12'}];
}
else
{
self.storage.theThird = [{id: 1, label: '2016-01'}, {id: 3, label: '2016-03'}, {id: 5, label: '2016-05'}, {id: 7, label: '2016-07'}, {id: 9, label: '2016-09'}, {id: 11, label: '2016-11'}];
}
}
}]);
})();
...
<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org" ng-app="app" ng-cloak ng-strict-di>
<head>
<meta charset="utf-8">
<title>{{app.title}}</title>
<script src="web/libs/jquery/dist/jquery.js"></script>
<script src="web/libs/angular/angular.js"></script>
<script src="web/js/javascript.js"></script>
<style>
label.optional:after
{
content: '*';
color: red;
}
/** Folowing style are just to ease the viewing of changes **/
main {display: flex; flex-direction: row-reverse}
main > aside {flex-grow: 1}
main > form {flex-shrink: 1}
</style>
</head>
<body>
<!-- You may declare your controller this way, or leave it to the responsibility of your router -->
<main ng-controller="DeviceController as ctrl">
<aside>
<pre>{{ctrl|json}}</pre>
</aside>
<form name="ctrl.forms.new"> <!-- This way, we can access our form inside the controller -->
<div>
<label for="new-device-family">
Family
</label>
<select
id="new-device-family"
ng-model="ctrl.data.family"
ng-change="ctrl.events.familyChanged()"
ng-options="family.id as family.label for family in ctrl.storage.families">
<option></option> <!-- this empty option will allow an unselected state -->
</select>
</div>
<div>
<label for="new-device-type" class="optional">
Type
</label>
<select
id="new-device-type"
ng-model="ctrl.data.type"
ng-change="ctrl.events.typeChanged()"
ng-options="type.id as type.label for type in ctrl.storage.types">
<option></option> <!-- this empty option will allow an unselected state -->
</select>
</div>
<div>
<label for="new-device-the-third">
The Thrid
</label>
<select
id="new-device-the-third"
ng-model="ctrl.data.theThird"
ng-options="theThird.id as theThird.label for theThird in ctrl.storage.theThird">
<option></option> <!-- this empty option will allow an unselected state -->
</select>
</div>
<hr>
<button type="reset" ng-click="ctrl.forms.new.$setPristine(); ctrl.forms.new.$setUntouched()">
Reset
</button>
<button type="sumbit" ng-disabled="!ctrl.data.theThird"> <!-- Disabled if the third is any falsy value -->
Reset
</button>
</form>
</main>
</body>
</html>

Categories

Resources