Identifying targetList in ember-drag-sort - ember.js

I am currently trying to implement an ember-drag-sort nested list into my Ember.js app.
Is there a way to determine in the dragEnd action which "sub-list" the item has been dropped into? (e.g. a class name, id etc)
In my scenario, I am sorting ember data records that can belong to each other (i.e. a nested, 'tree' structure). When I drag one nested record "into" another (making the dragged record a child of the second record), I need to update the parent attribute in ember-data. My question is, how do you pass some id of the second record (the new parent) to the dragEnd action?
Is this even possible?
EDIT:
To put it another way, I want to be able to identify which list I have dropped the item into.

targetList refers to the array on the dragged side of the component. For pushing the parent to the target list alongside the child, you can take a look at this twiddle.

To simplify identification of lists, the additional arguments feature has been implemented by #rwwagner90 (SO, GitHub).
You can pass some kind of list identifier into the additionalArgs argument to your lists. In this example I'm passing parent records which own the lists:
{{#each parents as |parent|}}
{{#drag-sort-list
items = parent.children
additionalArgs = (hash parent=parent)
dragEndAction = (action 'dragEnd')
as |child|
}}
{{child.name}}
{{/drag-sort-list}}
{{/each}}
In the dragEnd action you can access the parent records that own the source list and the target list:
dragEndAction({ sourceList, sourceIndex, sourceArgs, targetList, targetIndex, targetArgs }) {
if (sourceModel === targetModel && sourceIndex === targetIndex) return;
const item = sourceList.objectAt(sourceIndex);
sourceList.removeAt(sourceIndex);
targetList.insertAt(targetIndex, item);
// Access the parent via `sourceArgs` and `targetArgs`
sourceArgs.parent.save();
targetArgs.parent.save();
}

Related

How to get current line on change in slate.js

How does one get the current line, or the currently edited node, within the onChange or onKeyDown methods in Slate.js?
I'm trying to add an updatedAt or createdAt parameter in the data attribute for a particular line.
Here's a proof of concept for what I'm trying to do:
onChange = ({ value }) => {
return value.document.nodes.reduce((change, node) => {
return change.setNodeByKey(node.get("key"), {
data: {
createdAt: new Date(),
...node.get("data").toJS(),
},
});
}, value.change()).value;
}
This loops through every node and adds a createdAt attribute in data if one is not already present. This is obviously not great code since it's looping through every node and has to unserialize the Immutable data object for each node, but it hopefully illustrates what I'm looking to do.
How do I set the data attribute for just the current node?
A few things I've learned:
anchorkey gets you the current key of the selection
Value has a useful shortcut, startKey
Using the currently selected key, you can then loop through the nodes on a document to get the current node.
I'm not sure if Slatejs provides a way to grab a node by key; if so I can't find it, but the above gets me to where I want.

Ember.js - run observer after computed property has completed

I have an Ember.js app that includes a template with a carousel that contains a scrollable list of 'activities.' I'm using a computed property to filter and return a collection of activities, which I then use to bind to my template, which populates the carousel. The computed property that provides the collection looks like this:
// simplified for clarity
activities: function () {
var model = this.get('model.content');
model.sort(function (a, b) {
return (a.get('type') > b.get('type') ? 1 : -1;
}.bind(this);
return model;
}.property('model', 'controllers.browse.filter')
Every time the controllers.browse.filter property changes, the activities computed property is re-calculated, and the new filter criteria is applied to the model, which is working without a problem.
However, I need to 'rebind' my carousel after the newly filtered model is returned. Right now, I'm trying to do that with an observer like so:
reloadCarousel: function () {
// pseudo code, not important to problem
carousel.reload();
}.observes('activities')
The problem is that reloadCarousel is being run as soon as the activities property starts changing, meaning the activities property has not had time to complete and return the new model collection before the reloadCarousel observer is fired. This doesn't work, because my carousel isn't able to bind to the newly filtered model.
I searched the Ember.js docs, but can't find anything that allows me to wait until a computed property has completely finished and returned all relevant data to my template.
Any suggestions or ideas are greatly appreciated!
The get method returns a promise, which you could wait to fulfill and then set the activities:
this.get('model.content').then(function(model) {
var activities = model.sort(function (a, b) {
return (a.get('type') > b.get('type') ? 1 : -1;
});
// set activities
});

cfwheels - removing unused composite key pairs

I've got an issue with a nested property that uses a composite key.
When I'm editing a model that has multiple instances of nested properties (with a composite key) and want to update it to have fewer by leaving them blank, cfWheels does not remove the ones that are not used anymore, and maintains the old value. Is there a way of forcing the deletion of these without calling delete on the nested model?
I've been doing by deleting all nested properties, and then update() creates the records that are needed, but the big issue with that is that when I have code in between that fails, It just deletes the items, which as you know can be very very bad.
In your init call to nestedProperties(), try adding the allowDelete option:
nestedProperties(association="comments", allowDelete=true);
Then if a model within that collection has a property called _delete that is set to true, CFWheels will delete that record.
I'm not sure of your model because you don't include any details in your question, but you could probably run a beforeValidationOnUpdate callback that checks criteria on the nested models and sets _delete = true when the record needs to be deleted.
For example:
// Post.cfc
component extends="Model" {
function init() {
hasMany("comments");
nestedProperties(association="comments", allowDelete=true);
beforeValidationOnUpdate("removeBlankComments");
}
private function removeBlankComments() {
if (StructKeyExists(this, "comments") && IsArray(this.comments)) {
for (local.i = 1; local.i < ArrayLen(this.comments); local.i++) {
if (!Len(this.comments[local.i].message)) {
this.comments[local.i]._delete = true;
}
}
}
}
}
Not sure if this will give you any problems with the nested composite key. Sometimes nested properties are a little kludgy with "special" cases.
i think you forgot to mention allowDelete attribute in nestedProperties by defalut allowDelete is set as false in wheels and does not delete the composite key form table. you have to set it true.
for example in model you have to do some thing like this.
<cfset hasMany(name="campaignlanguages",shortcut="languages", dependent="deleteAll") />
<cfsetnestedProperties(associations="campaignlanguages",allowDelete="true")/>
you can find more details here

How to access back-forward list of UIWebView

How can we get the no of list items in bad-forward list of UIWebView? What I wanted to do is when back list is empty (ie. when there is no link to go back) navigate to previous controller. So wanted to know the count in the list.
Thanks in advance
Sayali
you dont want to access backforward list just for that, simply use .canGoBack property.
Here is the way to do it anyways (be carefull, private API here) :
id webview111 = [self _documentView]; /// self - uiwebview subclass
coreWebV = [webview111 webView];
backForwardList = [coreWebV backForwardList];

sencha touch :: how to create list of hbox-items

i want to generate a list of data out of a store. each data item holds a title and a boolean. now i want to have a list of the items, each holding the title and a togglefield (showing the boolean) on the right of the title.
how could I do that?
thnx!
From the Sencha Touch documentation, a List is "a mechanism for displaying data using a list layout template", i.e. html template. If you want a 'list' of components, you'll have to make your own extension of DataView (I think).
A workaround could be to put an html checkbox inside your itemTpl.
Something like (warning - not tested):
itemTpl: '<p>{title}: <input type="checkbox" name="BoolCheckbox" class="boolcheckbox"'
+ "{[(values.bool? 'checked="checked"' : '')]}"
+ '></input></p>'
To run your own code in the XTemplate, you bracket it with {[]}. When in this scope, you have access to a variable 'values', which contains the data for the record.
To detect events, you'd add a listener to the list:
itemtap: function (dataView, index, item, e) {
if (e.getTarget().getClass().toString() == "boolcheckbox") {
// do something
}
}
Some resources on templates:
http://dev.sencha.com/deploy/touch/docs/
http://www.sencha.com/learn/xtemplates-part-i/
http://www.sencha.com/learn/xtemplates-part-ii/