I've got the following code that successfully loads a garment. Chrome ember inspector shows that both Garment and its related model have loaded but I can't seem to display the related model (garment_colors) in the template.
Would really appreciate any help!
{{log garment_colors}} logs an empty array Class {type: function, content: Array[0], store: Class, _changesToSync: OrderedSet, loadingRecordsCount: 0…}__ember1410723197678: "ember522"__ember_meta__: Object__nextSuper: undefined_changesToSync: OrderedSetcontent: Array[0]isLoaded: trueisPolymorphic: undefinedloadingRecordsCount: 0name: "garment_colors"owner: Classstore: ClasstoString: function () { return ret; }type: App.GarmentColor__proto__: Object ember-1.7.0.js:14463
var attr = DS.attr,
belongsTo = DS.belongsTo,
hasMany = DS.hasMany;
App.Garment = DS.Model.extend({
name: attr(),
brand: attr(),
description: attr(),
materials: attr(),
garment_colors: hasMany('garmentColor')
});
App.GarmentColor = DS.Model.extend({
name: attr(),
color: attr(),
garment: belongsTo('garment')
});
App.DesignerRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('garment',params.id);
},
setupController: function(controller, model) {
controller.set('content', model)
console.log(model);
},
});
My json
{
"garment":{
"id":2,
"name":"Ultra shirt",
"brand":"Gildan",
"description":"this is the description",
"materials":"5.6 oz. 50% preshrunk cotton, 50% polyester.",
"garment_color_ids":[
66,
67,
68
]
},
"garment_colors":[
{
"id":66,
"name":"Purple",
"color":"#4f237a"
},
{
"id":67,
"name":"Light Blue",
"color":"#89b4df"
},
{
"id":68,
"name":"Carolina Blue",
"color":"#91b0e6"
}
]
}
Template - other attributes like name and brand display properly.
<script type="text/x-handlebars" data-template-name="designer">
{{outlet}}
<div id="product-details">
<h4>Style</h4>
<p id="name">{{name}}</p>
<p id="brand">{{brand}}</p>
<p id="description">{{description}}</p>
<p id="materials">{{materials}}</p>
<h4>Color</h4>
{{log garment_colors}}
<div id="color-list">
{{#each garment_colors}}
<label class="btn" style="background-color:{{color}}">
<input type="radio" name="color" value="{{name}}">
</label>
{{/each}}
</div>
</div>
</script>
The RESTAdapter expects the attribute name to be garment_colors.
"garment_colors":[
66,
67,
68
]
Adding in values like this isn't supported in handlebars, depending on certain versions it will add metamorph tags into the html.
<label class="btn" style="background-color:{{color}}">
<input type="radio" name="color" value="{{name}}">
</label>
You'll either need to make it unbound, which will inject it right into the template, but won't be bound to the model.
<label class="btn" style="background-color:{{unbound color}}">
<input type="radio" name="color" value="{{unbound name}}">
</label>
Or you'll need to use bind-attr to bind the attribute to the property
<label class="btn" {{bind-attr style=someProperty}}>
<input type="radio" name="color" {{bind-attr value=name}}>
</label>
Example: http://emberjs.jsbin.com/OxIDiVU/1077/edit
Related
I have a simple dynamic radio button, in my example 3 are created from returning data.
When a radio value is selected it populates my reactive form with that value, "yes", "no" or "maybe". In theses objects there are other properties that I would like to be sent back as part of the form.
As below I return section, but also want to return sectionCode of the matched section.
Before radio selection is changed my form shows all properties correctly, but obviously I can only pass back one value, so as soon as I do the other object items are lost.
https://stackblitz.com/edit/angular-r4g6uv?file=src%2Fapp%2Fpersonal%2Fpersonal.component.ts
section:[
{
section: "yes",
sectionCode: "1"
},
{
section: "no",
sectionCode: "2"
},
{
section: "maybe",
sectionCode: "3"
}
]
component.html
<div formGroupName="radioButtons" class="form-group col-6 pl-0 pt-3">
<h2 class="mb-2">radioButtons</h2>
<label for="intel-form-submitter" appRequiredLabel>select</label><br />
<div class="form-check-inline" *ngFor="let item of personal.radioButtons.section">
<label for="{{item.section}}" class="col-12 customradio"
><span>{{item.section}}</span>
<input value="{{item.section}}" id="{{item.section}}" type="radio" formControlName="section"/>
<span class="checkmark"></span>
</label>
</div>
</div>
component.ts
createEntry(formBuilder: FormBuilder) {
return this.formBuilder.group({
title: this.personal.title,
creationDate: this.personal.creationDate,
radioButtons: this.formBuilder.group({
section: this.personal.radioButtons.section,
})
});
}
hope this helps you.
Bind the object instead of one value in the object. In Component.html
[value]="item"
Component.html
<form [formGroup]="form" novalidate>
<div formGroupName="radioButtons" novalidate>
<div class="form-check-inline" *ngFor="let item of section">
<label for="{{item.section}}" class="col-12 customradio"
><span>{{item.section}}</span>
<input **[value]="item"** id="{{item.section}}" type="radio" formControlName="section"/>
<span class="checkmark"></span>
</label>
</div>
</div>
<button type="button" (click)="save()" >Save</button>
</form>
{{form.value|json}}
Component.ts
xport class AppComponent implements OnInit {
section = [
{
section: "yes",
sectionCode: "1"
},
{
section: "no",
sectionCode: "2"
},
{
section: "maybe",
sectionCode: "3"
}
];
selectedSection: any;
form: FormGroup;
constructor(public formBuilder: FormBuilder) {}
ngOnInit() {
this.form = this.createEntry();
}
createEntry() {
return this.formBuilder.group({
radioButtons: this.formBuilder.group({
section: this.section[0]
})
});
}
save(){
console.log(this.form)
}
}
Find project in - https://stackblitz.com/edit/k-react-form-radio-test-5bixbv
You can bind the object itself instead of just section name.
<input [value]="item" id="{{item.section}}" type="radio"/>
Demo : https://stackblitz.com/edit/angular-h1mwhe
I am learning Vuejs and I am trying to develop a form and my browser went blank when I began to develop this code in User.vue:
<template>
<div class="users">
<h1>Users</h1>
<form v-on:submit="addUser">
<input type="text" v-model="newUser.name" placeholder="Enter Name">
<br />
<input type="text" v-model="newUser.email" placeholder="Enter Email">
<br />
<input type="submit" value="Submit">
</form>
<ul>
<li vi-for="user in users">
<input type="checkbox" class="toggle" v-model="user.contacted">
<span :class="{contacted: user.contacted}">
{{user.name}}: {{user.email}}
</span>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'users',
data() {
return {
newUser: {},
users: [
{
name: 'Brad Traversy',
email: 'techguy#gmail.com',
contacted: false
},
{
name: 'Hendrik John',
email: 'hjohn#gmail.com',
contacted: false
},
{
name: 'Brooke Dukes',
email: 'bdukes#automattic.com',
contacted: false
}
]
}
},
methods: {
addUser: function(e){
this.users.push({
name: this.newUser.name,
email: this.newUser.email,
contacted: false
});
e.preventDefault();
}
},
}
</script>
<style scoped>
.contacted{
text-decoration: line-through;
}
</style>
I seem to be getting Cannot read property of undefined for the properties inside the users array, but I have been unable to figure out why.
Simple syntax error here:
<li vi-for="user in users">
Should be
<li v-for="user in users">
FWIW, I expect the error was along the lines of "can't read the property contacted of undefined" which is a javascript error indicating that user is undefined. Then you just look at where user should be defined to find your error.
Im trying to edit the selected item from the main view list in a separate html view, so when the save button is clicked the changes are reflected to the list in the main view.Im my edit I have used title,description,from and to dates to edit.I got struck with an idea here, that is, what if the user only wants to edit any one of the four details and save the rest details the same, I tried it with the ng-model but it could read only the edited details but not the already existing one. So I'm looking for a help in this.
Html:
<div align="center">
Title
<input type="text" ng-model="selectInput.Title">
Offer:
<input type="text" ng-model="selectInput.data.description">
Valid from:
<input type="date" ng-click="FromDate()" ng-model="frDate">
<br> Valid till:
<input type="date" ng-click="ToDate()" ng-model="toDate" />
</div>
<hr>
<button ng-click='SaveEdit($index)' ng-model="editSave"> Save</button>
controller:
$scope.items = [];
$rootScope.couponList = [{ Title: "Fruit Export Details" data: {description: "consume soon product", Fromdate: "2016-09-09", Todate: "2016-09-18"}},
{Title: "Vegetables Export Details", data:{description: "consume soon product", Fromldate: "2016-11-09", Todate: "2016-10-19"}},
{ CouponTitle: "Saviours",data:{description: "storable", Fromldate: "2016-09-10", Todate: "2016-10-09"}}];
$scope.select_item = function (key) {
//alert(key);
$scope.items.push(key);
}
$scope.SaveEdit=function(){
$scope.Title=$scope.selectInput.data.Title;
$scope.description=$scope.selectedInput.data.description;
$scope.Fromdate=$scope.selectInput.data.Fromdate;
$scope.Todate=$scope.selectInput.data.Todate;
}
$state.go('app.WashType');
}
I think you are problem is mismatching of ng-model names in your controller
HTML (MODIFIED)
<div align="center">
Title
<!-- <input type="text" ng-model="selectInput.Title"> -->
<input type="text" ng-model="$scope.selectInput.data.Title">
Offer:
<input type="text" ng-model="$scope.selectedInput.data.description">
Valid from:
<!-- <input type="date" ng-click="FromDate()" ng-model="frDate">-->
<input type="date" ng-click="FromDate()" ng-model="$scope.selectInput.data.Fromdate">
<br> Valid till:
<!-- <input type="date" ng-click="ToDate()" ng-model="toDate" /> -->
<input type="date" ng-click="ToDate()" ng-model="$scope.selectInput.data.Todate" />
</div>
<hr>
<button ng-click='SaveEdit($index)' ng-model="editSave"> Save</button>
JS
$scope.items = [];
$rootScope.couponList = [{ Title: "Fruit Export Details" data: {description: "consume soon product", Fromdate: "2016-09-09", Todate: "2016-09-18"}},
{Title: "Vegetables Export Details", data:{description: "consume soon product", Fromldate: "2016-11-09", Todate: "2016-10-19"}},
{ CouponTitle: "Saviours",data:{description: "storable", Fromldate: "2016-09-10", Todate: "2016-10-09"}}];
$scope.select_item = function (key) {
//alert(key);
$scope.items.push(key);
}
$scope.SaveEdit=function(){
$scope.Title=$scope.selectInput.data.Title;
$scope.description=$scope.selectedInput.data.description;
$scope.Fromdate=$scope.selectInput.data.Fromdate;
$scope.Todate=$scope.selectInput.data.Todate;
}
$state.go('app.WashType');
}
Your ng-model values don't line up with what you're using in the controller.
The first two set a property on the selectInput property of the $scope and the data property on the selectInput property on the scope, but $scope never seems to get an object selectInput assigned to it, let along it having a data property.
In your controller you should add during initialization:
$scope.selectInput = {data:null};
The third and fourth fields have names that don't line up at all with the scope.
HTML
<div align="center">
Title
<input type="text" ng-model="selectInput.data.Title">
Offer:
<input type="text" ng-model="selectInput.data.Description">
Valid from:
<input type="date" ng-click="FromDate()" ng-model="selectInput.data.FromDate">
<br>
Valid till:
<input type="date" ng-click="ToDate()" ng-model="selectInput.data.ToDate" />
</div>
<hr>
<button ng-click='SaveEdit()'> Save</button>
Controller
$scope.items = [];
$rootScope.couponList = [...items here...];
$scope.select_item = function (key) {
//alert(key);
$scope.items.push(key);
}
$scope.SaveEdit = function(){
// Do stuff with
// $scope.selectInput.data.Title;
// $scope.selectInput.data.Description;
// $scope.selectInput.data.FromDate;
// $scope.selectInput.data.ToDate;
}
I have one controller, controller's template/view as below,
myController
angular.module('myApp', []).
controller('myController', ['$scope', function($scope) {
$scope.myObject = {};
}]);
myView
<div class="container" ng-app="myApp">
<form name="myForm" novalidate ng-controller="myController">
<div class="form-group">
<label for="firstname" class="control-label col-xs-2">Name</label>
<div class="col-xs-10">
<input type="text" ng-model="myObject.firstname" id="firstname">
</div>
</div>
<div class="form-group">
<label for="lastname" class="control-label col-xs-2">LastName</label>
<div class="col-xs-10">
<input type="text" ng-model="myObject.lastname" id="lastname">
</div>
</div>
</form>
</div>
here whenever user enters any data it gets reflected to myObject with firstname and lastname as dynamic properties for myObject.
Now my new requirement is to add multiple dynamic views for firstname and lastname in the same view(For that I will be creating a directive and appending dynamically), and now I want myObject to be an array of objects like
myObjectArray = [{firsname: "abc", lastname: "xyz"},{firsname: "abc", lastname: "xyz"},{firsname: "abc", lastname: "xyz"},{firsname: "abc", lastname: "xyz"}]
and here each object should be populated through dynamically added views by user input using angular two way binding. But I am not sure how can I achieve this with angular, how to add object to array whenever there is a new directive template added to view dynamically.
In Angular you should avoid thinking in terms of dynamic controls.
Here is the approach
You want to list firstname, lastname objects
You want to add a new object to this list.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.items = [];
$scope.itemsToAdd = [{
firstName: '',
lastName: ''
}];
$scope.add = function(itemToAdd) {
var index = $scope.itemsToAdd.indexOf(itemToAdd);
$scope.itemsToAdd.splice(index, 1);
$scope.items.push(angular.copy(itemToAdd))
}
$scope.addNew = function() {
$scope.itemsToAdd.push({
firstName: '',
lastName: ''
})
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="plunker" ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<div ng-repeat="item in items">
{{item.firstName}} {{item.lastName}}
</div>
<div ng-repeat="itemToAdd in itemsToAdd">
<input type="text" ng-model="itemToAdd.firstName" />
<input type="text" ng-model="itemToAdd.lastName" />
<button ng-click="add(itemToAdd)">Add</button>
</div>
<div>
<button ng-click="addNew()">Add new</button>
</div>
</body>
Notice these are simply talking about model. Here is a plunk
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>