Is there a way to supply the columnDefs to ui-grid with a promise? - angular-promise

The data for the ui-grid seems to support a promise of the data, but the columnDef option does not seem to. If the data coming in is dynamic and the column defs are also loaded dynamically how can the columns definition be specified with a promise.

You can supply your columnDefs the promise's return value in your .then() handler:
$scope.gridOptions = {
data: [ ... ]
};
ColumnService.getColumns()
.then(function (columnDefs) {
$scope.gridOptions.columnDefs = columnDefs;
});

Related

How to structurally compare the previous and new value of nested objects that are being used in `watch`, in Options API?

I have a question which is a mix of both composition API and options API
What I want to do: I want to watch an object. That object is deeply nested with all kinds of data types.
Whenever any of the nested properties inside change, I want the watch to be triggered.
(This can be done using the deep: true option).
AND I want to be able to see the previous value and current value of the object.
(this doesn't seem to be possible because Vue stores the references of the objects, so, now the value and prevValue point to the same thing.)
In Vue3 docs, for the watch API, it says this
However, watching a reactive object or array will always return a reference to the
current value of that object for both the current and previous value of the state.
To fully watch deeply nested objects and arrays, a deep copy of values may be required.
This can be achieved with a utility such as lodash.cloneDeep
And this following example is given
import _ from 'lodash'
const state = reactive({
id: 1,
attributes: {
name: ''
}
})
watch(
() => _.cloneDeep(state),
(state, prevState) => {
console.log(state.attributes.name, prevState.attributes.name)
}
)
state.attributes.name = 'Alex' // Logs: "Alex" ""
Link to docs here - https://v3.vuejs.org/guide/reactivity-computed-watchers.html#watching-reactive-objects
However, this is composition API (if I'm not wrong).
How do I use this way of using cloneDeep in a watch defined in options API?
As an example, this is my code
watch: {
items: {
handler(value, prevValue) {
// check if value and prevValue are STRUCTURALLY EQUAL
let isEqual = this.checkIfStructurallyEqual(value, prevValue)
if (isEqual) return
else this.doSomething()
},
deep: true,
},
}
I'm using Vue 3 with Options API.
How would I go about doing this in Options API?
Any help would be appreciated! If there's another way of doing this then please do let me know!
I also asked this question on the Vue forums and it was answered.
We can use the same syntax as provided in the docs in Options API using this.$watch()
data() {
id: 1,
attributes: {
name: ''
}
}
this.$watch(
() => _.cloneDeep(this.attributes),
(state, prevState) => {
console.log(state.name, prevState.name)
}
)
this.attributes.name = 'Alex' // Logs: "Alex" ""

How to set columnOption looping throw all column?

How to set the columnOptions looping through all in angular devexpress module?
at present I do one by one like :
onInitialized(e) {
e.component.columnOption("Id", {
allowHeaderFiltering : false -> 1
})
e.component.columnOption("Name", {
allowHeaderFiltering : false -> 2
})
e.component.columnOption("SaleAmount", {
editorOptions: {
format: "currency",
showClearButton: true
}
});
}
How to look all column and set the columnOptionon each?
If you need to initialize a column with default settings (I believe you need to do this since you provided the onInitialized event handler code), use the customizeColumns callback function. Its parameter is an array of all columns in the grid. Thus, you can traverse through all columns as you do in a regular array.
Since customizeColumns is a callback function, use square brackets to assign a function to it in Angular as described in the Callback Functions section:
*.component.html
<dx-data-grid [customizeColumns]="customizeColumns">
</dx-data-grid>
*.component.ts
export class AppComponent {
customizeColumns (columns) {
columns.forEach(c => c.width = 100);
}
}

fullcalendar with resourceDay, update list of resources

I am using fullcalendar v1.5.4 with the resourceDay view (https://gist.github.com/anonymous/9c9ce0d84a6a73080177). My problem is when I am trying to update the list of resources. I can just run setCalendar() but it's quite a big and resource expensive function:
setCalendar = function (defaultView, element, currentDate) {
myCal = $(element);
myCal.fullCalendar({
minTime: '07:00:00',
maxTime: '23:59:00',
cache: true,
editable: true,
eventStartEditable: true,
eventDurationEditable: true,
...
resources: [ resourcesArray ],
dayClick: function (date, event, t, r) {
...
}
...
});
}
Running all of this code every time I want to update the columns of the resourceDay view is too expensive so I am trying to update only the list of columns (resources) and rerender them. In the function ResourceManager of the gist that I linked above (row 1257) you can see that I have tried to lift the function that populates the list of resources. By adding t._addResourceSources = _addResourceSources; and then calling on it from this function:
updateCalendar = function () {
myCal.fullCalendar('_addResourceSources', resourcesArray);
};
This is printing the new list to the console (row 1305) but I need assistance with rerendering it so the calendar actually uses the new list of resources.
Try running myCal.fullCalendar( 'rerenderEvents' );
http://fullcalendar.io/docs1/event_rendering/rerenderEvents/
It may not work though, I don't know how resources work exactly and I'm more familiar with the v2 of fullCalendar.

Meteor: sharing variables between helpers

I am currently building a quizz app in Meteor and have three function within helpers
Template.quizPage.helpers({
//this helper finds the currentquiz and returns the currentquestion to the template
question: function(){
currentquiz = this.quiztitle;
currentQuestion = Session.get('currentQuestion') || 0;
return Quizzes.findOne({'quiztitle': currentquiz}).quizquestions[currentQuestion]
},
length: function (){
questionlength = $(Quizzes.findOne({'quiztitle': currentquiz}).quizquestions).length;
return questionlength;
},
answers: function(){
currentquiz = this.quiztitle;
currentQuestion = Session.get('currentQuestion') || 0;
return Quizzes.findOne({'quiztitle': currentquiz}).answers[1][currentQuestion]
}
});
As you can see some of this code is already duplicate (currentquiz = this.quiztitle). How can I share currentquiz between functions within a helper?
This is becoming a real problem as I need to define the variable currentquiz one time
currentQuestion = [0,0,0,0,0];
But current code resets the currentquestion any time I activate the helper in the template. I can;t define it above the function $(document.ready) wrap to set the variable or define it . This should be really easy right?
i know this is an old thread but I just came across the same problem. What you can do is define a reactive variable on the template level:
var abc;
Template.XY.rendered = function(){
abc = new ReactiveVar("abc");
},
Template.XY.helpers({
someFunction:function(){
return abc.get();
}
)}
I define a var abc; to bind the variable to the template instance (i guess this can also be done with this.abc = new ... )
To provide a variable available in the template helpers and events you just need to add it in the template instance.
In the onCreated function you can access the template instance with the keyword this.
Template.myTemplate.onCreated(function(){
this.mySharedVariable = new ReactiveVar("myValue");
});
In the helpers you can access to the templace instance with Template.instance().
Template.myTemplate.helpers({
myHelper1(){
const instance = Template.instance();
instance.mySharedVariable.get(); // Get the value "myValue"
// Do something
},
myHelper2(){
const instance = Template.instance();
instance.mySharedVariable.get(); // Get the value "myValue"
// Do something
}
});
In the events you can access to the template instance with the second parameter of the function.
Template.myTemplate.events({
'click .js-do-something' : function(event, instance){
instance.mySharedVariable.set("newValue"); // Set the value "newValue"
}
});
In the example above i'm using a ReactiveVar so if its value get changed the two helpers myHelper1 and myHelper2 will re-execute. But be free to use normal variable depending on your need.
PS: Because Session are global, you should not use Session if you only use this "shared" variable inside your template.

How to 'transform' data returned via a Meteor.publish?

Meteor Collections have a transform ability that allows behavior to be attached to the objects returned from mongo.
We want to have autopublish turned off so the client does not have access to the database collections, but we still want the transform functionality.
We are sending data to the client with a more explicit Meteor.publish/Meteor.subscribe or the RPC mechanism ( Meteor.call()/Meteor.methods() )
How can we have the Meteor client automatically apply a transform like it will when retrieving data directly with the Meteor.Collection methods?
While you can't directly use transforms, there is a way to transform the result of a database query before publishing it. This is what the "publish the current size of a collection" example describes here.
It took me a while to figure out a really simple application of that, so maybe my code will help you, too:
Meteor.publish("publicationsWithHTML", function (data) {
var self = this;
Publications
.find()
.forEach(function(entry) {
addSomeHTML(entry); // this function changes the content of entry
self.added("publications", entry._id, entry);
});
self.ready();
});
On the client you subscribe to this:
Meteor.subscribe("publicationsWithHTML");
But your model still need to create a collection (on both sides) that is called 'publications':
Publications = new Meteor.Collection('publications');
Mind you, this is not a very good example, as it doesn't maintain the reactivity. But I found the count example a bit confusing at first, so maybe you'll find it helpful.
(Meteor 0.7.0.1) - meteor does allow behavior to be attached to the objects returned via the pub/sub.
This is from a pull request I submitted to the meteor project.
Todos = new Meteor.Collection('todos', {
// transform allows behavior to be attached to the objects returned via the pub/sub communication.
transform : function(todo) {
todo.update = function(change) {
Meteor.call('Todos_update', this._id, change);
},
todo.remove = function() {
Meteor.call('Todos_remove', this._id);
}
return todo;
}
});
todosHandle = Meteor.subscribe('todos');
Any objects returned via the 'todos' topic will have the update() and the remove() function - which is exactly what I want: I now attach behavior to the returned data.
Try:
let transformTodo = (fields) => {
fields._pubType = 'todos';
return fields;
};
Meteor.publish('todos', function() {
let subHandle = Todos
.find()
.observeChanges({
added: (id, fields) => {
fields = transformTodo(fields);
this.added('todos', id, fields);
},
changed: (id, fields) => {
fields = transformTodo(fields);
this.changed('todos', id, fields);
},
removed: (id) => {
this.removed('todos', id);
}
});
this.ready();
this.onStop(() => {
subHandle.stop();
});
});
Currently, you can't apply transforms on the server to published collections. See this question for more details. That leaves you with either transforming the data on the client, or using a meteor method. In a method, you can have the server do whatever you want to the data.
In one of my projects, we perform our most expensive query (it joins several collections, denormalizes the documents, and trims unnecessary fields) via a method call. It isn't reactive, but it greatly simplifies our code because all of the transformation happens on the server.
To extend #Christian Fritz answer, with Reactive Solution using peerlibrary:reactive-publish
Meteor.publish("todos", function() {
const self = this;
return this.autorun(function(computation) {
// Loop over each document in collection
todo.find().forEach(function(entry) {
// Add function to transform / modify each document here
self.added("todos", entry._id, entry);
});
});
});

Resources