May I know how can I disable the rest of the checkbox except for step 2,3 and 4? Those checkbox are link from the checkbox component. And i link the checkbox component into route at columns propertyName:"active". Below is a part of the route code.
export default Route.extend({
model() {
let results = {
workflow: {
columns: [
{
"propertyName": "step",
"title": "Step",
editable: false
},
{
"propertyName": "workflowName",
"title": "Workflow Name",
},
{
"propertyName": "preferredName",
"title": "Your Company Preferred Name",
},
{
"propertyName": "active",
"title": "Active",
component: "adk-workflow-select-row",
editable: false
},
{
title: "Edit",
component: "edit-row",
editable: false
}],
rows: [
{
step: '0',
workflowName: 'New',
preferredName: '新',
},
{
step: '1',
workflowName: 'Budget Approval',
preferredName: '预算批准',
},
{
step: '2',
workflowName: 'Creative',
preferredName: '创作的',
},
{
step: '3',
workflowName: 'Visualize',
preferredName: '想象',
},
{
step: '4',
workflowName: 'Implementation',
preferredName: '履行',
},
{
step: '5',
workflowName: 'In Play',
preferredName: '活性',
},
{
step: '6',
workflowName: 'Completed',
preferredName: '已完成',
},
{
step: '7',
workflowName: 'Canceled',
preferredName: '取消',
},
]
},
This is the adk-workflow-select-row which is the checkbox component. The code below is how i render the checkbox at. This enable all the checkbox. But i only need step 2,3 and 4 checkbox to be enable.
{{#paper-checkbox value=isSelected onChange=(action "clickOnRow" index record)}}{{/paper-checkbox}}
Your questions is a bit hard to answer because you dont show the relevant template code.
Generally you somehow call your your checkbox in your template, and you can just wrap this in an {{#if. Your code is very generic, but I just guess this could be in your edit-row component. So like this:
{{#if some condition}}
{{#paper-checkbox value=isSelected onChange=(action "clickOnRow" index record)}}{{/paper-checkbox}}
{{/if}}
Now the important question is what condition to use. And this kind of depends on what exactly you want. How do you want to configure it? Do you want to keep a global array somehow saying which steps have the checkbox in your rows like this?
{
step: '2',
workflowName: 'Creative',
preferredName: '创作的',
showCheckbox: true,
},
Depending on this what you want could be something like this:
{{#if record.showCheckbox}}
{{#paper-checkbox value=isSelected onChange=(action "clickOnRow" index record)}}{{/paper-checkbox}}
{{/if}}
generally if you're new to ember I can just strongly recommend you to first try to learn how things work in a less generic situation. A generic solution like you have can be awesome, but soon become very complex.
Related
we would like to add lazy loading functionality to our ember project, but it looks like ember will always override fields not returned by the response JSON with NULL. First I get a list of users:
GET https://example.com/users
{
"users": [
{
"id": 1,
"name": 'user1',
"email": 'email#user1.com',
"images": [],
"posts": []
},
{
"id": 2,
"name": 'user2',
"email": 'email#user2.com',
"images": [],
"posts": []
},
{
"id": 3,
"name": 'user3',
"email": 'email#user3.com',
"images": [],
"posts": []
},
]
}
This provides a minimal set of user information, with two empty hasMany relations "images" and "posts".
Now, if somebody want to see the users posts or images he would click a button which triggers the lazy loading:
GET https://example.com/userImages/1
{
"user": {
"id": 1,
"images": [1,2,3,4]
},
"images": [
{
"id": 1,
"name": "image1",
"path" "path/to/img1/"
},
{
"id": 2,
"name": "image2",
"path" "path/to/img2/"
},
{
"id": 3,
"name": "image3",
"path" "path/to/img3/"
},
{
"id": 4,
"name": "image4",
"path" "path/to/img4/"
}
]
}
To reduce traffic to a minimum, only the newly loaded information is included. After the adapter has deserialzed and pushed the new data to the store, all fields from User1 which are not included in the payload (name, email) are set to NULL in the ember store (tested with store.pushPayload('model', payload)).
Is there a possibility to update only incoming data? Or is there a common best practice to handle such a case?
Thanks in advance for your help
EDIT:
One possibility would be to extend the ember-data "_load()" function with the block
for (var key in record._data) {
var property = record._data[key];
if( typeof(data[key]) == 'object' && data[key] == null ) {
data[key] = property;
}
}
But this is the worst possible solution I can imagine.
I think what you want is the store's update method. It's like push (or pushPayload), except that it only updates the data that you give it.
Your property returns a promise and that promise returns whatever came back from the server.
foobar: function() {
return this.store.find('foobar');
}
When the promise resolves, you have two versions of the data, the one already rendered in the client (dataOld) and the one that just returned from the backend (dataNew). To update the client without removing what hasn't change, you have to merge the old and the new. Something along the lines of:
foobar: function() {
var dataOld = this.get('foobar');
return this.store.find('foobar').then(function(dataNew) {
return Ember.$.merge(dataOld, dataNew);
});
}
Does igGrid support column edit/new templates?
I have a grid defined as below. But the template won't work when editing/adding a new row.
The "ChooseEmployee" function displays a popup dialog for users to choose employee's from.
$(function() {
var employees = [{
Id: 1,
"Name": "John, Smith",
"DirectReports": "Mary, Ann;David,Lowe"
}, {
Id: 2,
"Name": "Mary, Ann",
"DirectReports": "Kelly,Walsh;Kevin, Edwards;Terri, Gibson"
}];
$('#grid1').igGrid({
dataSource: employees,
primaryKey: "Id",
autGenerateColumns: false,
width: "100%",
columns[{
headerText: "Id",
key: "Id",
dataType: "number",
width: 100
}, {
headerText: "Name",
key: "Name",
dataType: "string",
width: 120
}, {
headerText: "Reports",
key: "DirectReports",
dataType: "object",
width: 300,
template: "<div style='clear:both'><div style='overflow:hidden;white-space:wrap;max-width:320px;width:320px;float:left;'>${DirectReports}</div><input type='button' onclick='chooseEmployees(${Id});' value='...' style='float:left;' /></div>"
}],
features: [ {name: "Updating", enableAddRow: true, editMode: "row" } ]
});
});
<table id="grid1"></table>
Basically you would have to cancel the original row editing that the igGrid is performing and you would have to invoke row updating and row adding programmatically. Also this template will work for rows that already exist, but would not be applied when adding a new row. You can try the Row Edit Template feature of the igGrid as it provides in the box editing dialog. If you want to choose from a list of values for this specific column, then you can use a combo editor provider for this column.
Option for configuring editor provider for the column.
updateRow API method.
addRow API method.
Setting up a row edit template.
I found custom select for ember
https://gist.github.com/pixelhandler/6320922 . It's based on components and works well.
But I have one trouble. Data source for select is shared between all instances of it.
And I want to set default value as the first element of the data set but when I change value in one select it changes everywhere. Can you help me with it? Here is example: http://emberjs.jsbin.com/guhobutafado/19/edit
In your example, your select boxes all refer to the same data set with binding, so, of course, when one changes, all of them do... That's the principle of data-binding.
Then you have to use different data sets for your problem, to save the modifications on each select. Without this, you can't access to the data on each one, because they point to the same thing.
You can use multiple arrays like this:
App.IndexController = Ember.Route.extend({
name: 'one',
className: 'dropdown',
choices1: [
{ choice: 'Choose One' },
{ choice: 'First' },
{ choice: 'Last' }
],
choices2: [
{ choice: 'Choose One' },
{ choice: 'First' },
{ choice: 'Last' }
],
choices3: [
{ choice: 'Choose One' },
{ choice: 'First' },
{ choice: 'Last' }
]
});
Then call your faux-select components with each independent array:
{{faux-select name=name className=model.className
choices=choices1 selected=choices1.[0].choice}}
{{faux-select name=name className=model.className
choices=choices2 selected=choices2.[0].choice}}
{{faux-select name=name className=model.className
choices=choices3 selected=choices3.[0].choice}}
Here's a JSBin with this philosophy in action.
I am facing a situation in which I need to persist an embedded relationship into database. I am describing a similar situation in this question. It is an ember-cli project.
I have two models:
//app/model/post.js
import DS from 'ember-data';
var Post = DS.Model.extend({
entry: DS.attr('string'),
comments: DS.hasMany('comment')
});
export default Post;
//app/models/comment.js
import DS from 'ember-data';
var Comment = DS.Model.extend({
text: DS.attr('string'),
post: DS.belongsTo('post')
});
export default Comment;
1 Serializer:
//app/serializers/post.js
import DS from 'ember-data';
export default DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
comments: {
embedded: 'always'
}
}
});
1 Route:
//app/routes/index.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.find('post', 1);
},
setupController: function(controller, model) {
var newComment = this.store.createRecord('comment', {});
newComment.set('text', 'xxxx comment');
model.get('comments').pushObject(newComment);
model.save().then(function(){
console.log(model.toJSON());
comments = model.get('comments');
comments.forEach(function(comment){
console.log("Comment: " + comment.get('text'));
console.log("Comment id: " + comment.get('id'));
});
});
}
});
So, the GET call in model hook the server returns:
// GET /posts/1
{
"posts": {
"id": "1",
"entry": "This is first post",
"comments": [
{
"id": "1",
"post": "1",
"text": "This is the first comment on first post"
},
{
"id": "2",
"post": "1",
"text": "This is the second comment on first post"
}
]
}
}
When in the setupController hook, I add a new comment to the post and save it, its actually sending a PUT request with the following body:
// PUT /posts/1 -- Request
{
"posts": {
"id": "1",
"entry": "This is first post",
"comments": [
{
"id": "1",
"post": "1",
"text": "This is the first comment on first post"
},
{
"id": "2",
"post": "1",
"text": "This is the second comment on first post"
},
{
"post": "1",
"text": "xxxx comment"
}
]
}
}
The server returns the following output:
// PUT /posts/1 -- Response
{
"posts": {
"id": "1",
"entry": "This is first post",
"comments": [
{
"id": "1",
"post": "1",
"text": "This is the first comment on first post"
},
{
"id": "2",
"post": "1",
"text": "This is the second comment on first post"
},
{
"id": "3",
"post": "1",
"text": "xxxx comment"
}
]
}
}
But now in the console log I get the following output:
Comment: This is the first comment on first post
Comment id: 1
Comment: This is the second comment on first post
Comment id: 2
Comment: xxxx comment
Comment id: 3
Comment: xxxx comment
Comment id: null
Why is the new comment returned with id is added to the post's comments and is not replacing the comment?
Am I doing anything wrong or I need to add something else for this?
Ember Data would have no exact way of recognizing the difference between a record that user attempted to save and a record a different user attempted to save.
All it can safely know is that a new record with a new id came back (since there was no unique identifier on the record before, and you didn't specify to save that exact record).
In a non multi-user world, it could assume the new record should replace the existing record, but the Embedded Record stuff just isn't that smart yet.
1. Delete the record after you save (cause you know it'll get duped, hacky)
var comments = model.get('comments');
comments.pushObject(newComment);
model.save().then(function(){
comments.popObject(newComment);
newComment.deleteRecord(); // not really necessary
...
});
2. Save the record from the comment's point of view (cheapest and cleanest, might be a bit of additional server side logic for you)
newComment.save();
Here,I am trying to implement CRUD operations using ember-model.
I am totally new to ember environment,actually i don't have much understanding of ember-model.
Here,i am trying to add new product and delete existing one.I am using inner node of fixture
i.e. cart_items.My this fixture contains two node i.e. logged_in and cart_items and this what my fixture structure :
Astcart.Application.adapter = Ember.FixtureAdapter.create();
Astcart.Application.FIXTURES = [
{
"logged_in": {
"logged": true,
"username": "sachin",
"account_id": "4214"
},
"cart_items": [
{
"id": "1",
"name": "Samsung Galaxy Tab 2",
"qty": "1",
"price": "100",
"subtotal": "100"
},
{
"id": "2",
"name": "Samsung Galaxy Tab 2",
"qty": "1",
"price": "100",
"subtotal": "100"
},
{
"id": "3",
"name": "Samsung Galaxy Tab 2",
"qty": "1",
"price": "100",
"subtotal": "100"
}
]
}
];
I want to this fixture struture only to get data in one service call from server.
Now,here is my code which i am using to add and delete product from cart_items
Astcart.IndexRoute = Ember.Route.extend({
model: function() {
return Astcart.Application.find();
}
});
Astcart.IndexController = Ember.ArrayController.extend({
save: function(){
this.get('model').map(function(application) {
var new_cart_item = application.get('cart_items').create({name: this.get('newProductDesc'),qty: this.get('newProductQty'),price: this.get('newProductPrice'),subtotal: this.get('newProductSubtotal')});
new_cart_item.save();
});
},
deleteproduct: function(product){
if (window.confirm("Are you sure you want to delete this record?")) {
this.get('model').map(function(application) {
application.get('cart_items').deleteRecord(product);
});
}
}
});
But when i am trying to save product i am getting an exception
Uncaught TypeError: Object [object global] has no method 'get'
And when i am trying to delete product i am getting an exception
Uncaught TypeError: Object [object Object] has no method 'deleteRecord'
Here,i also want to implement one functionality i.e. on every save i need to check if that product is already present or not.
If product is not present then only save new product other wise update existing product.
But i don't have any idea how to do this?
I have posted my complete code here.
Can anyone help me to make this jsfiddle work?
Update
I have updated my code here with debugs.
Here, i am not getting any exception but record is also not getting delete.
I am not getting what is happening here?
Can anyone help me to make this jsfiddle work?
'this' context changes within your save method. You need to use the 'this' of the controller and not the map functions. Try this:
save: function(){
var self = this;
self.get('model').map(function(application) {
var new_cart_item = application.get('cart_items').create({
name: self.get('newProductDesc'),
qty: self.get('newProductQty'),
price: self.get('newProductPrice'),
subtotal: self.get('newProductSubtotal')
});
new_cart_item.save();
});
}