Qml: pass argument as part of URL when loading components from files - c++

Is there a mechanism to pass URL arguments in Qml and extract them later?:
StackView.push("Page.qml?#label2);
Regards,

You can "pass arguments" when creating an object from a component.
StackView.push(component.createObject(null, {"someProperty" : someValue}))
So you can use an auxilary component to facilitate that:
Component { id: component; url: "Page.qml" } // or
property Component component: Qt.createComponent("Page.qml") // or
Component { id: component; Page {} }
Or if you don't want to pollute with extra stuff, you can directly:
StackView.push(Qt.createComponent("Page.qml").createObject(null, {"someProperty" : someValue}))
Lastly, not a good idea to have your StackView named StackView, I mean in QML neither properties nor ids can begin with uppercase character.

No need to create an object manually. Just do this
stackView.push(Qt.resolvedUrl("qrc:/U/R/L/item.qml"), {someCustomProperty: 0})

This is NOT worked:
navigationBar.push(Qt.resolvedUrl('qrc:/Pages/BookListPage.qml'), {argument:'test'})
But this is worked (to create an object):
navigationBar.push(Qt.createComponent("qrc:/Pages/BookListPage.qml").createObject(null, {argument:'test'}))

Actually according to the QT docs ([http://doc.qt.io/qt-5/qml-qtquick-controls-stackview.html][1]) the recommended way is to pass a property list containing at least the the following minimum entries to the push function ():
item: this property is required, and holds the item to be pushed.
properties: a list of QML properties to be assigned to the item upon push. These properties will be copied into the item at load
time, or when the item will become the current item (normally upon
push).
so we get
navigationBar.push({item: Qt.resolvedUrl("MyRectangle.qml"), properties: {"color" : "red"}});

Related

Identifying targetList in ember-drag-sort

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();
}

Parent property is not bind to the child (Ember 2.8)

My code:
signup.emblem:
= validating-form onsubmit=(action 'signUp')
= input-field value=username
span {{usernameError}}
validating-form.js:
submit(event) {
console.log(this.get('username') //undefined
this.sendAction('onsubmit')
}
signup.js:
actions: {
signUp() {
console.log(this.get('username')) // value from input
}
}
As you can see the basic idea is some value in input gets validated in validating-form component and then if everything is fine it'll call some controller action or set some properties.
The problem is that apparently this form component isn't bind to properties from controller, even though its child component (input-field) is. Can you tell me what am I doing wrong here?
If I have to bind it explicitely, is there some way to do that with multiple properties at once?
The problem is that the standard input element isn't two-way bound to your username variable. You can bind it quickly using the action and mut helpers.
(example in handlebars, but you should be able to convert to emblem easily enough)
<input value={{username}} onblur={{action (mut username) value='target.value'}}>
This is saying:
on the onblur event
mut(ate) the username
to match the current target.value - which is the value of the input box
You can see evidence of this working in this twiddle
The other option is Input Helpers
I've not used these, as they don't follow the current Ember thinking of Data Down Actions Up, but it should be as simple as:
{{input value=username}}
And this will two-way-bind directly username.

EmberJS, Helper with an "as" block

I have an Object and then I have a Decorator that consumes the Object and returns a Human-friendly representation of the Object.
For example:
object = { id: "XXX1", detail: "XXX2" }
decoratedObject { title: "The Red Building", detail: "Has 101 stories" }
I would like to use the Decorator in a template:
{{#decorator-helper object as |decoratedObject|}}
<h1>{{decoratedObject.title}}</h1>
<p>{{decoratedObject.detail}}</p>
{{/decorator-helper}}
How can I do this?
You should use a component for this.
Generally you should use helpers if you want to use them to calculate other values like this:
{{my-component value=(my-helper val)}}
If you want to use block syntax you should use a component.
As far as I know you cannot do this with helpers. Why don't you define a computed property called decoratedObject on your controller or component that would be based on object ?
decoratedObject: Ember.computed('object', {
get() {
// Build your decorated object and return it
return decoratedObject;
}
})
This would make your decorated object available in your template and dynamically rebuild it when object changes.

TypeError: Object #<Object> has no method 'set'

once a certain process is done I need to set a boolean to true in order to update the template.
I can easily get the object, but setting a property seems to be more difficult. What I use to get the object is
var found = self.get('content').findProperty('id', self.datasetid);
If I do that in the chrome console I can clearly see that I get an ember object back:
Object {id: 1, active: true}
__ember1364221685101_meta: Meta
active: true
get data_set: function () {
id: 1
set data_set: function (value) {
__proto__: Object
When I do:
found.set('data_set.fully_geocoded', true);
I do get the error mentioned in title. I've tried as many different flavours as I could think of, but all with the same result.
Could somebody shine a light on this?
An Object isn't an instance of Ember.Object, but the base Javascript class Object, so it won't have a get and set method.
You can get much of the same functionality by using Ember.get and Ember.set directly, passing in the object, as such:
Ember.set(found, 'data_set.fully_geocoded', true)
Ember.get(found, 'data_set.fully_geocoded')
Computed properties and observers can also fire based on using Ember.set this way.

Force a controller to always act as a proxy to a model in Ember

I'm looping through a content of an ArrayController whose content is set to a RecordArray. Each record is DS.Model, say Client
{{# each item in controller}}
{{item.balance}}
{{/each}}
balance is a property of the Client model and a call to item.balance will fetch the property from the model directly. I want to apply some formatting to balance to display in a money format. The easy way to do this is to add a computed property, balanceMoney, to the Client object and do the formatting there:
App.Client = DS.Model({
balance: DS.attr('balance'),
balanceMoney: function() {
// format the balance property
return Money.format(this.get('balance');
}.property('balance')
});
This serves well the purpose, the right place for balanceMoney computed property though, is the client controller rather than the client model. I was under the impression that Ember lookup properties in the controller first and then tries to retrieve them in the model if nothing has been found. None of this happen here though, a call to item.balanceMoney will just be ignored and will never reach the controller.
Is it possible to configure somehow a controller to act always as a proxy to the model in all circumstances.
UPDATE - Using the latest version from emberjs master repository you can configure the array controller to resolve records' methods through a controller proxy by overriding the lookupItemController method in the ArrayController. The method should return the name of the controller without the 'controller' suffix i.e. client instead of clientController. Merely setting the itemControllerClass property in the array controller doesn't seem to work for the moment.
lookupItemController: function( object ) {
return 'client';
},
This was recently added to master: https://github.com/emberjs/ember.js/commit/2a75cacc30c8d02acc83094b47ae8a6900c0975b
As of this writing it is not in any released versions. It will mostly likely be part of 1.0.0.pre.3.
If you're only after formatting, another possibility is to make a handlebars helper. You could implement your own {{formatMoney item.balance}} helper, for instance.
For something more general, I made this one to wrap an sprintf implementation (pick one of several out there):
Ember.Handlebars.registerHelper('sprintf', function (/*arbitrary number of arguments*/) {
var options = arguments[arguments.length - 1],
fmtStr = arguments[0],
params = Array.prototype.slice.call(arguments, 1, -1);
for (var i = 0; i < params.length; i++) {
params[i] = this.get(params[i]);
}
return vsprintf(fmtStr, params);
});
And then you can do {{sprintf "$%.2f" item.balance}}.
However, the solution #luke-melia gave will be far more flexible--for example letting you calculate a balance in the controller, as opposed to simply formatting a single value.
EDIT:
A caveat I should have mentioned because it's not obvious: the above solution does not create a bound handlebars helper, so changes to the underlying model value won't be reflected. There's supposed to be a registerBoundHelper already committed to Ember.js which would fix this, but that too is not released yet.