I'm creating a portfolio item with a rallyaddnew button, but I'd like to modify it before it is created. For example, I'd like to add a particular parent, and add some tags.
I'm guessing I can modify the object in perhaps the beforeCreate() event. But if I do so what methods do I use? I see that modifying record.data.Name actually seems to work, but what is the correct way to do it?
For something like parent or tags, I figure I need a Rally.util.Ref object. But again, what is the correct way to modify the object? Doing a record.data.Tags.push(ref) in response to a beforeCreate event again seems a bit direct...
Using the beforeCreate listener, you're given the record to modify:
var addNew = Ext.widget('rallyaddnew', {
recordTypes: ['User Story'],
ignoredRequiredFields: ['Name', 'ScheduleState', 'Project'],
listeners: {
beforeCreate: function(addNewComponent, record) {
record.set('Name', 'new name');
record.set('Parent', '/hierarchicalrequirement/123.js')
}
}
});
So, use the record.set function to set data, and for properties that are references like Parent you should use the ref string, like /hierarchicalrequirement/123.js (if you have a record, you can get the ref with record.get('_ref').
Related
I am looking for a way to replace the object under data.
data() {
return {
form:{ .... }
}
}
I have learnt that I cannot directly change data itself so I moved all my variables under form. I want to replace all the data inside the form so that my form values are changed.
I have found a way to update single values like this;
this.$set(this.someObject, 'planes', true) where the solution is here but I want to replace all the form object.
update_form(){
let self = this
$.ajax({
url: '/formdata/',
type: 'GET',
success: function(response){
self.$set(self.form, needToUpdateAll)
}
});
},
I am stuck right where it says needToUpdateAll. From the docs, it says target, key, value.
I am looking for a solution because I do not want to assign all values one by one (well the object has nested and nested objects :()
Any walk-around would be appreciated
This is not complicated. You don't need $set. Is update_form() in methods? If so, just do this.form = response. Top level names in your data are directly available in the rest of your Vue object.
I have a form for updating document entity.
The document entity consists of list of employees (which is an array of objects) and each employee has a post which is just a string.
I have a dropdown (kind of wrapper for vue-multiselect) which accepts the array of employees and syncs selected employee to a selectedEmployee variable in data().
And also I have a watcher for selectedEmployee which sets the post input automatically when an employee is selected in the dropdown.
So, when creating a document in the form everything's fine, however, when I update the document, then I fetch existing document from server, set selectedEmployee and set employee's post. But, the document also keeps employee's post, so the first time when I open document's form in order to update it, I don't want to automatically update document's post. I want it to be updated only when user actually selects employee himself.
But the watcher gets called the first time too.
So, imagine we have John Doe and his a manager. When I create the document, I change his post to designer. Then, I open up the document form in order to update it, and I should see that for this specific document John Doe's post is "designer", but the watcher gets called and returns the post to manager.
I tried to make a fake variable in data(), like doneFetching, but it works only if I update this var directly in watcher, which looks quite dangerous, plus, in other entities I have many different kinds of selected employees, so making tons of fake flags is not an option.
Here is real code sample (employee = representative in my case):
selectedApproveRepresentative(representative) {
if (!representative) {
this.memoData.approve_representative_id = null
return
}
this.memoData.approve_representative_id = representative.id
// Here is temporary solution, but I have many watchers for many different kinds of employees. If I move the doneFetching flag after I initialized the form, it'll be set to true, and only after that the watcher will be called
if (this.mode === 'update' && !this.doneFetching) {
this.doneFetching = true
return
}
// In normal case a representative might have or have not post, so depending on this case we set it to be empty or filled. But this should not be called the first time I open the form
this.memoData.approve_representative_post_dative_case =
representative.post_dative_case ?
representative.post_dative_case : ''
},
Here is where I initialize data:
created() {
if (this.memo) {
this.memoData = _.cloneDeep(this.memo)
this.selectedApproveRepresentative = _.cloneDeep(this.memo.approve_representative)
}
},
as I understood, your problem is the watcher executed when you init the component. Have you tried setting the immediate property of the watcher to false?
Not everybody knows that the watchers can be defined in different ways.
The simple one that everybody know
watchers: {
propertyToWatch() { //code... }
}
Passing the name of a function as 'string'
watchers: {
propertyToWatch: 'nameOfAfunctionDefinedInMethodsSection'
}
The object declaration
This one is the most descriptive way of declaring a watcher. You write it as an object with a handler property (it can be the name of a function passed as string as above), and other properties like deep to watch nested properties of an object, or in your case immediate which tells to the watcher if the should run immediately when the component is mounted.
watchers: {
propertyToWatch: {
immediate: false,
handler: function() { //code.. }
}
}
I'm trying to respond to a change in one of the properties of the model in a widget. To be clear, when the value of the property changes, I want to run some code to react to the change. In a parent widget I have a date picker which changes the date in the model.
I cannot get the custom setter to be called _setParentPropertyAttr...
If I include this in my widget
<span data-dojo-type="dojox/mvc/Output" data-dojo-props="value: at(rel:, 'ParentProperty')">
It works nicely. Changing the date picker outputs the current value to the page. So I can supply the value property to the output widget when the date changes in the model. But what I need to do (I think) is supply a custom property with the date property in the model when the date picker changes the value.
I realise this question is a bit vague but I can't provide the code as it's proprietary.
I've tried to break the problem down by setting a property manually within my widget as:
myProperty:0,
...
constructor
...
_setMyPropertyAttr: function(value):
{
console.log("setting myproperty");
}
....
this.set('myProperty', 5);
....
but that isn't working either.
If you set a property within a widget does that not call the custom setter?
I'm struggling a bit because there aren't so many dojo examples out there any help is much appreciated.
You can bind an event to be called when a widget's property is set/update or you can even use watch to do that.
But this only works using the set function, using someWidget.someProperty = 5; wont work.
Let me show you how dojo do it. The basic about the magic setters and getters is explained here.
_set: function(/*String*/ name, /*anything*/ value){
// summary:
// Helper function to set new value for specified property, and call handlers
// registered with watch() if the value has changed.
var oldValue = this[name];
this[name] = value;
if(this._created && !isEqual(oldValue, value)){
if(this._watchCallbacks){
this._watchCallbacks(name, oldValue, value);
}
this.emit("attrmodified-" + name, {
detail: {
prevValue: oldValue,
newValue: value
}
});
}
}
This peace of code is from dijit/_WidgetBase, the _set function is what dojo calls after a set is called, and is where it finally set the property value this[name] = value; and as you can see, it emit an event that will be called attrmodified-propertyName and also call a watchCallbacks.
For example, if in some place, we have this:
on(someWidget, 'attrmodified-myproperty', function(){
console.log(someWidget.get('myProperty'));
});
and then we use:
someWidget.set('myProperty', 'Hello World!');
The event will be triggered. Note that someWidget.myProperty = 'Hello World!' wont trigger the event registration. Also note that if in our widget we define the magic setter:
_setMyPropertyAttr: function(value) {
//do something here with value
// do more or less with other logic
//but some where within this function we need to cal "_set"
this._set('myProperty', value);
}
without calling _set, the magic wont happen.
As i said at the beginning, we can also use watch:
someWidget.watch('myProperty', function(){
console.log(someWidget.get('myProperty'));
});
Note that we can register to this events or the watch function within the same widget.
Also, as a plus, the magic setter can be triggered when creating the widget with just passing the property name in the constructor object param, this work for the declarative syntax too, for example:
var someWidget = new MyWidget({
'myProperty': 'Hello World!!'
});
and
<div data-dojo-type="MyWidget" data-dojo-props="myProperty: 'Hello World!!'"></div>
both will triggered a call to the _setMyPropertyAttr if exist, or dojo will use the magic setter in the case it doesn't exist.
Hope it helps
Consider using custom setter on your widget, where you can add your custom logic.
Example of definition of custom setter on your widget:
_setOpenAttr: function(/*Boolean*/ open){
// execute some custom logic here
this._set("open", open);
}
Example of setting a property on your widget:
widgetRef.set('open', true);
Alternatively you can could consider using dojo/store/Observable.
dojo/store/Observable store wrapper that adds support for notification of data changes.
You can read more about it on the followign link:
https://dojotoolkit.org/reference-guide/1.10/dojo/store/Observable.html
If figured out the problem. If I set a watch on the model I can then check if indiviual properties have changed in the watch function. I knew it would be something simple!
I have two components inside a parent, one component shows me a list, and I want the other component to show me the details of an item of the list. I'm using the List of this demo https://elements.polymer-project.org/elements/neon-animation?view=demo:demo/index.html&active=neon-animated-pages
since I have these two components
<list-view data="[[fileData]]" on-item-click="_onItemClick"></list-view>
<full-view on-close="_onClose"></full-view>
I would like to pass the Id of an item clicked on list-view to the full-view. So what would be the best way to execute an event on "full-view" when an item of "list-view" is clicked? I need to pass information from list-view to full-view.
Thank you.
What about of databinding? #SG_ answer is ok, but it can does using simple databinding, as follows:
<list-view data="[[fileData]]" on-item-click="_onItemClick" selected-id="{{idSelected}}"></list-view>
<full-view on-close="_onClose" selected-id="{{idSelected}}"></full-view>
Each element models should have a property "Selected ID", to make it possible to perform databinding. In <full-view> you must need to add a property as follows:
selectedId:{type:String, observer:"selectedIdChanged"}
So, when selectedId changes in <list-view> will also change in <full-view>
Now, you only need to add a new function in <full-view> to do something with this changed selectedId
selectedIdChanged: function(newValue, oldValue){
if(newValue!= undefined && newValue!=null){
//do something with selected Id
}
},
You could give an id for both list-view and full-view, then define & set data attribute/property for <full-view> from the _onItemClick.
<list-view id='l_view' data="[[fileData]]" on-item-click="_onItemClick"></list-view>
<full-view id="f_view" data="{}" on-close="_onClose"></full-view>
And in the script of parent.
_onItemClick: function() {
this.$.f_view.data = this.$.l_view.selected;//or any attribute of the selected item
this.$.pages.selected = 1;
},
Hopefully I'm describing this correctly. I'm making a windows store app and I have the following setup
WinJS.Namespace.define("Model",
{
WorkOrders: new WinJS.Binding.List(),
selectedWorkOrder: {}
});
WinJS.Namespace.define("ViewModel",
{
WorkOrders: Model.WorkOrders,
selectedWorkOrder: Model.selectedWorkOrder
})
When the page is loaded an ajax request populates a list of WorkOrders, after they're populated a user can select one, at which point Model.selectedWorkOrder is set to one of the objects in Model.WorkOrder.
I want ViewModel.selectedWorkOrder to reflect whatever Model.selectedWorkOrder is, but it seems to bind only to the originally empty object, how can I make it bind to that property (even if the object changes, like a pointer).
I'm doing something like this to set the selectedWorkOrder
Model.selectedWorkOrder = results[i];
Thanks!
Not sure if I understand your question correctly.
What you're looking for is some kind of event to get in ViewModel.selectedWorkOrder whatever Model.selectedWorkOrder has, right?
If that's the case you could try RxJS-WinJS (which I'm honestly not too familiar with) or you could just make ViewModel.selectedWorkOrder a method that gets and returns whatever Model.selectedWorkOrder has at any given time.
Something like this:
WinJS.Namespace.define("Model",
{
WorkOrders: new WinJS.Binding.List(),
selectedWorkOrder: {}
});
var _getWorkItem = function(){
return Model.selectedWorkItem;
}
WinJS.Namespace.define("ViewModel",
{
WorkOrders: Model.WorkOrders,
selectedWorkOrder: _getWorkItem
})