Using underscore.js groupBy with Ember.js - ember.js

Is it possible to use underscore's groupBy function with ember.js?
I have the following attempt which is obviously not working:
var activities = App.store.findMany(App.Activity, feed.mapProperty('id').uniq())
var grouped = _.groupBy(activities, function(activity){
return activity.get('dateLabel;')
});
I get the following error:
Object App.Activity has no method 'get'
The store is loaded with the correct data so findMany will not make a remote call.
The problem is that findMany returns a DS.ManyArray which is probably a lot different than what _.groupBy is looking for.

You could implement your own groupBy function tailored for ember-data DS-ManyArray objects and extend _ with it:
_.emberArrayGroupBy = function(emberArray, val) {
var result = {}, key, value, i, l = emberArray.get('length'),
iterator = _.isFunction(val) ? val : function(obj) { return obj.get(val); };
for (i = 0; i < l; i++) {
value = emberArray.objectAt(i);
key = iterator(value, i);
(result[key] || (result[key] = [])).push(value);
}
return result;
};
Now you can call
var grouped = _.emberArrayGroupBy(activities, function(activity) {
return activity.get('dateLabel');
});
or more simply
var grouped = _.emberArrayGroupBy(activities, 'dateLabel');
The function above is based on underscore's original groupBy() implementation, which looks very similar:
_.groupBy = function(obj, val) {
var result = {};
var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
each(obj, function(value, index) {
var key = iterator(value, index);
(result[key] || (result[key] = [])).push(value);
});
return result;
};

Try this code:
var activities = App.store.findMany(App.Activity, feed.mapProperty('id').uniq())
var grouped = _.groupBy(activities, function(activity){
return activity.get('dateLabel;')
}).bind(this);
I did not run this code to test how it works but the idea is to 'bind' outer scope into inner closure function scope.
Hope this helps to get you some ideas...

Related

Add an another attribute to an existing List in Flutter

I have been trying many ways to add an isChecked: false attribute to every list inside the _filterOptions List in my Flutter Project. I couldn't find any solution to this. If there is any solution I am happy to see it.
List<dynamic> _filters = [];
List<List<dynamic>> _filterOptions =[];
var filters =
await json.decode(data)["getProductsByStore"]["aggregations"];
for(int i = 0; i < filters.length; i++){
_filters.add(filters[i]["label"]);
_filterOptions.add(filters[i]["options"]);
}
//print(filters[0]["options"]);
//print(_filters);
print(_filterOptions);
I am getting this kind of nested list when printed and I want to add the attribute to every list.
as an example:
[[{count: 3, label: 30-40, value: 30_40, isChecked:false}], [{count: 2, label: Bagged , value: 50, isChecked:false},{...},{...}...]]
Create Model class with your data and bool isChecked
class ModelClass{
String? label;
int? count;
List? options;
bool? isChecked;
ModelClass({this.label, this.count , this.options, this.isChecked = false});
ModelClass.fromJson(Map<String, dynamic> json){
label = json['label'];
count = json['count'];
options = json['options'];
}
}
then you can add data like below code
List<ModelClass> list = [];
void function()async{
List<dynamic> _filters = [];
List<List<dynamic>?> _filterOptions =[];
var filters =
await json.decode(data)["getProductsByStore"]["aggregations"];
for(int i = 0; i < filters.length; i++){
ModelClass modelClass = ModelClass.fromJson(filters[i]);
list.add(modelClass);
_filters.add(modelClass.label);
_filterOptions.add(modelClass.options);
}
print(list[0].options);
print(list[0].isChecked);
}
if you want to modify isChecked for some specific index
list[0].isChecked = false;
Just add these lines.
class YourWrapperClass {
YourWrapperClass({this.filterOptions = const [], this.isChecked = false});
List<List<dynamic>> filterOptions;
bool isChecked;
}
YourWrapperClass filterWrapper = YourWrapperClass(filterOptions: _filterOptions, isChecked: false);
And use this wrapper class object whenever ya need to access _filterOptions.
But, I would more rather recommend using the WrapperClass on the list elements, like so.
class YourWrapperClass {
YourWrapperClass({this.filterOption = const [], this.filter="", this.isChecked = false});
List<dynamic> filterOption;
dynamic filter;
bool isChecked;
}
List<YourWrapperClass> list = [];
var filters =
await json.decode(data)["getProductsByStore"]["aggregations"];
for(int i = 0; i < filters.length; i++){
list.add(YourWrapperClass(filterOption:filters[i]["options"], filter:filters[i]["label"], isChecked=false));
_filterOptions.add(filters[i]["options"]);
}

How to add dynamic values to field injections list with custom trigger to camunda properties panel?

I have two questions here
Is it possible to add dynamic lists values to field injection list input ?
Can I create a trigger for this so this can be initiated from any other input selection say a class selection will populate all fields
I was just looking into FieldInjection.js whether that can be extented for the same
Can someone please provide a hint or direction for this ?
Thanks.
For anyone interested in the answer, I was able to achieve the above goal by changing the set function of the Java Class select input as folllowing
few imports
var extensionElementsHelper = require('../../../../helper/ExtensionElementsHelper'),
elementHelper = require('../../../../helper/ElementHelper')
var CAMUNDA_FIELD_EXTENSION_ELEMENT = 'camunda:Field';
function getExtensionFields(bo) {
return bo && extensionElementsHelper.getExtensionElements(bo, CAMUNDA_FIELD_EXTENSION_ELEMENT) || [];
}
then changing the set function to create extension element and push the field values as :
set: function(element, values, node) {
var bo = getBusinessObject(element);
var type = getImplementationType(element);
var attr = getAttribute(type);
var prop = {}
var commands = [];
prop[attr] = values.delegate || '';
var extensionElements = getExtensionFields(bo);
//remove any extension elements existing before
extensionElements.forEach(function(ele){
commands.push(extensionElementsHelper.removeEntry(getBusinessObject(element), element, ele));
});
if(prop[attr] !== ""){
var extensionElements = elementHelper.createElement('bpmn:ExtensionElements', { values: [] }, bo, bpmnFactory);
commands.push(cmdHelper.updateBusinessObject(element, bo, { extensionElements: extensionElements }));
var arrProperties = ["private org.camunda.bpm.engine.delegate.Expression com.cfe.extensions.SampleJavaDelegate.varOne","private org.camunda.bpm.engine.delegate.Expression com.cfe.extensions.SampleJavaDelegate.varTwo"]
var newFieldElem = "";
arrProperties.forEach(function(prop){
var eachProp = {
name:"",
string:"",
expression:""
}
var type = prop.split(" ")[1].split(".").reverse()[0];
var val = prop.split(" ")[2].split(".").reverse()[0];
eachProp.name = val;
if( type == "String"){
eachProp.string = "${" + val +" }"
}else if( type == "Expression"){
eachProp.expression = "${" + val +" }"
}
newFieldElem = elementHelper.createElement(CAMUNDA_FIELD_EXTENSION_ELEMENT, eachProp, extensionElements, bpmnFactory);
commands.push(cmdHelper.addElementsTolist(element, extensionElements, 'values', [ newFieldElem ]));
});
}
commands.push(cmdHelper.updateBusinessObject(element, bo, prop));
return commands;
}
Cheers !.

How do I return the result of Ember.RSVP.all from a function?

The function below needs to return a true or false. Inside the then call at the bottom of the function, I get the value I need from result.isAny('hasOverride') but I don't know how to return this value from the hasRoomUpcharge function. How do I do this? I thought adding return in front of Ember.RSVP.all would do it, but it doesn't work. Please help!
hasRoomUpcharge: function(roomRates, defaultRoomTypeCode){
var defaultRoomRates = roomRates.findBy('roomTypeCode', defaultRoomTypeCode);
var nonDefaultRoomRates = roomRates.rejectBy('roomTypeCode', defaultRoomTypeCode);
var nonDefaultRoomMasters = this.modelFor('propertyPricing').roomTypeMasters.rejectBy('isDefault');
var promises = [];
var promise;
nonDefaultRoomMasters.forEach(function(roomMaster){
var roomTypeCode = roomMaster.get('roomTypeCode');
promise = roomMaster.get('roomRateUpcharge').then(function(roomRateUpcharge){
var currentRoomMasterOnePersonPrice = nonDefaultRoomRates.findBy('roomTypeCode', roomTypeCode).onePersonPrice;
var defaultRoomMasterOnePersonPrice = defaultRoomRates.onePersonPrice;
var roomUpcharge = roomRateUpcharge.get('onePersonRateUpcharge');
if(currentRoomMasterOnePersonPrice != defaultRoomMasterOnePersonPrice + roomUpcharge){
return { hasOverride: true };
}
else {
return { hasOverride: false };
}
});
promises.push(promise);
});
return Ember.RSVP.all(promises).then(function(result){
return result.isAny('hasOverride');
});
},
You cannot return the result from the hasRoomUpcharge function, as it returns before promises resolve (i.e. before the result is even known).
You are in fact doing it the right way - returning a promise from the hasRoomUpcharge function. When invoking this function, you should consume the returned promise, e.g.
this.hasRoomUpcharge(1, 3).then(function(result) {
console.log(result); //do something with the result
}

How to properly setup a store that acts as a single pointer across your web app

I have a home grown store that has a simple identityMap. When I return an array of models from this and bind it to a controllers "model" it reflects what you'd expect
the first time you hit a route it reflects this in the template as
you'd expect
But later if I get this same store instance (it's a singleton) and push an object into the identityMap it doesn't automatically update the previous template
The store itself is super basic (no relationships/ just push objects and get by id)
function buildRecord(type, data, store) {
var containerKey = 'model:' + type;
var factory = store.container.lookupFactory(containerKey);
var record = factory.create(data);
var id = data.id;
identityMapForType(type, store)[id] = record;
return record;
}
function identityMapForType(type, store) {
var typeIdentityMap = store.get('identityMap');
var idIdentityMap = typeIdentityMap[type] || {};
typeIdentityMap[type] = idIdentityMap;
return idIdentityMap;
}
var Store = Ember.Object.extend({
init: function() {
this.set('identityMap', {});
},
push: function(type, data) {
var record = this.getById(type, data.id);
if (record) {
record.setProperties(data);
} else {
record = buildRecord(type, data, this);
}
return record;
},
getById: function(type, id) {
var identityMap = identityMapForType(type, this);
return identityMap[id] || null;
}
getEverything: function(type) {
var identityMap = identityMapForType(type, this);
var keys = Object.keys(identityMap);
var values = [];
for (var i = 0; i < keys.length; i++)
{
var val = identityMap[keys[i]];
values.push(val);
}
return values;
}
});
Ember.onLoad('Ember.Application', function(Application) {
Application.initializer({
name: "store",
initialize: function(container, application) {
application.register('store:main', Store);
application.inject('controller', 'store', 'store:main');
application.inject('route', 'store', 'store:main');
}
});
});
In my model hook (in the find all route lets say) I simply query for each item and push them into the store
//inside my model find method lets say ...
find: function(store) {
var url = "/api/foo";
$.getJSON(url, function(response) {
response.forEach(function(data) {
var model = store.push("foo", data);
}
}
return store.getEverything("foo");
}
So I assumed my controllers' model was this bound array (using a single pointer in memory for this array of models)
Yet when I do this inside a controller submit action it won't re-render that prev view (to show the new item that was added to that store's array)
actions: {
submit: function() {
var foo = {}; // assume this is a real json response or js object
var store = this.get("store");
store.push("foo", foo);
}
}
Because of this today, I'm forced to get the parent controller and "set" / "push" this new object to it's content/model property :(
Anyone know what I'm doing wrong here?
I like homegrown solutions, they generally are easier to work with and meld around what you're working on.
So I'm actually surprised this part is working:
//inside my model find method lets say ...
find: function(store) {
var url = "/api/foo";
$.getJSON(url, function(response) {
response.forEach(function(data) {
var model = store.push("foo", data);
}
}
return store.getEverything("foo");
}
If I read through it I see you make an ajax call, and then return store.getEverything immediately after (without a guarantee that the ajax call has completed). Then inside of getEverything you create a new array called values then iterate the identity map linking up all of the currently available records and return that. At this point your store is unaware of this array going forward. So any changes to your store wouldn't get pushed out to the array, they might make it into the identity map, but it isn't feeding the getEverything array.
There are a couple of solutions, one would be to keep track of your everything array. That collection would be super cheap to build, more expensive to search, so keeping the identity map as well would be super beneficial. You could follow your same pattern, but one collection would be the map, whereas the other would be an array of everything.
Modified Build Record
function buildRecord(type, data, store) {
var containerKey = 'model:' + type;
var factory = store.container.lookupFactory(containerKey);
var record = factory.create(data);
var id = data.id;
identityMapForType(type, store)[id] = record;
everythingArrayForType(type, this).pushObject(record);
return record;
}
Copy paste, possibly could be refactored
function everythingArrayForType(type, store) {
var everythingArrays = store.get('everythingArrays');
var arr = everythingArrays[type] || [];
everythingArrays[type] = arr;
return arr;
}
Slightly modified Store
var Store = Ember.Object.extend({
init: function() {
this.set('identityMap', {});
this.set('everythingArrays', {});
},
push: function(type, data) {
var record = this.getById(type, data.id);
if (record) {
record.setProperties(data);
} else {
record = buildRecord(type, data, this);
}
return record;
},
getById: function(type, id) {
var identityMap = identityMapForType(type, this);
return identityMap[id] || null;
}
getEverything: function(type) {
return everythingArrayForType(type, this);
}
});

Get URL parameter - sharepoint

I am trying to extract an ID from my URL and paste it in the sharepoint List into the ID text box, I have tried it like that:
<script type=”text/javascript”>
function GetQueryStringParams(sParam)
{
var sPageURL = window.location.search.substring(1);
var sURLVariables = sPageURL.split('&');
for (var i = 0; i < sURLVariables.length; i++)
{
var sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] == sParam)
{
return sParameterName[1];
}
}
}​
document.forms['aspnetForm'].ctl00_m_g_d9f5e4f9_7e05_4a4d_88b7_a6b1dcdda667_ctl00_ctl01_ctl00_ctl00_ctl00_ctl04_ctl00_ctl00_TextField.value=GetQueryStringParams(‘ID’);
</script>
however it does not work, my URL:
http://Lists/Systems%20Survey/NewForm.aspx?Source=http://Lists/Systems%2520Survey/overview.aspx&ID=14-01234
I have put it as a web part xml on my web.
Do you have any idea what I did wrong? :)
thanks for assistance
Use the function below as getQueryVariable('source')
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
console.log('Query variable %s not found', variable);
}