I see a few ways to give Zend\View\Model\ViewModel::setVariables an array:
Implement in entity toArray() and make JsonModel($entity->toArray())
Use DoctrineModule\Stdlib\Hydrator\DoctrineObject and $hydrator->extract($entity);
Implement Iterator for entity and extends from it
And the question is, how can i implement iterator for Doctrine2 entity, and is it a good idea or maybe someone know a better way?
Generally, iterating an entity is a bad idea.
If you want to pass your entity to a view template, you can do the following:
<?php
// IndexController.php
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class IndexController extends AbstractActionController {
// The "index" action
public function indexAction() {
// Create your entity here
$entity = ...
// Pass it to view template for rendering
return new ViewModel(array(
'entity' => $entity
));
}
}
Then, in your view template, you will be able to access the entity in the following way:
<?php echo $this->entity->getId(); ?>
Related
I am working with Ember Octane version, I want to invoke an action in the Route from the child component. The pseudo code is as follows.
**Route**
export default class SomeRouter extends Route {
model() {
return data;
}
#action
refreshRoute() {
this.refresh();
}
}
**SomerRouter.hbs**
<ChildComponent> //Using child component here
**ChildComponent**
export default class ChildComponent extends Component {
#action
revert() {
//How do I invoke the "refreshRoute" on the SomeRouter from here?
}
}
In the revert method of the above child component, "this" refers to the component itself but in the previous version of the ember "this" refers to the router where I could simply call this.refresh(). So how do I achieve this in Ember Octane. Would really appreciate any help.
You dont. This is actually one of the things that are still a bit inconsistent even with octane. Because the bound context of the route template is the Controller, not the route. So you can not access the action with {{this.refreshRoute}}.
To call an action on the Route your best way is to uzilize send. But to do this you need a Controller and define a different action on the Controller:
controllers/some.js:
export default class SomeController extends Controller {
#action
refreshRouteFromController() {
this.send('refreshRoute');
}
}
Now this function you can use from your template:
<ChildComponent #refresh={{this.refreshRouteFromController}}>
And then use it from your component:
revert() {
this.args.refresh();
}
Or directly from a button:
<button {{on "click #refresh}}>...</button>
When trying to access the model of a controller when creating a computed property on the controller, I get the following error:
model.uniqBy is not a function
app/controller/ticket.js
export default Ember.Controller.extend({
statuses: Ember.computed('model', function() {
var model = this.get('model');
return model
.uniqBy('status')
.map(function(i) { return i.status; })
.toArray();
}),
});
The model I'm giving to the controller is a collection returned from this.store.findAll('ticket');, but trying to iterate through it seems to be causing the above error. Is the collection given to the model not supposed to be an Ember.Enumerable object? Should I be trying to access the collection via the DS.Store (in which case I don't understand the need to pass a model to the controller)?
Ember.computed.uniqBy
A computed property which returns a new array with all the unique elements from an array, with uniqueness determined by specific key
Please try this instead for your computed property
statuses: Ember.computed.uniqBy('model', 'status')
EDIT
You can use ember computed map on this property to fine tune your array if needed, for example like this
status: Ember.computed.map('statuses', function(status, index)
return status.toUpperCase() + '!';
})
Another way is that computed property uses dynamic aggregate syntax as described here
https://guides.emberjs.com/v2.6.0/object-model/computed-properties-and-aggregate-data/
so Ember.computed('model.#each.status', function()
Hope it helps
Here what i have done :
I have controller called "employee" and component "Department".
From controller i want to call the function of the component how can i it ?
controller: "Employee" ::
if (this.get("callMoveleft")) {
this.set("callMoveleft", false);
}
else {
this.set("callMoveleft", true);
}
Component : "Department" ::
callMoveLeft: function () {
console.log('Move left will be called');
}.observes("callMoveleft"),
Department's function is not getting called. Please suggest me where i am doing wrong ?
You should have a model that represents your component's state. This model will be available to the controller, so that it can call .moveLeft() on it.
The component should use this model's properties to display itself. Once the controller changes the model's state, the component will automatically update.
UPD
Demo: http://emberjs.jsbin.com/wizepi/1/edit?html,js,output
I have a component which has, inside it, a list of child components (being drawn with a yield inside the parent component):
parent-component
for item in items
child-component item=item childProperty=parentProperty
Inside child-component, I have an observer on "childProperty", which correctly fires any time parentProperty changes. The problem is that I'd like to trigger that observer in a time when the property hasn't actually changed.
to do this, in my parent-component, I have:
this.notifyPropertyChange('parentProperty')
For some reason, this isn't making it to the child component. Here's a JS bin showing:
http://emberjs.jsbin.com/caxedatogazo/1/edit
While I'm happy to talk through my use-case more, I'm more interested in whether the JS bin should work, and if not, why..
Thanks so much for any help!
When you call notifyPropertyChange on the controller, only observers registered within the controller are notified of the property change.
In your case, the observer is within the component controller and not the parent controller from where the notifyPropertyChange is called.
There is a hacky way to ensure that the component controller is notified of the property change. This can be done by adding the following method to the Component.
didInsertElement: function() {
var controller = this.get('targetObject');
controller.addObserver('foo', this, this.onDataChange);
},
What we are doing is, getting the parent controller, registering an observer for foo with the parent controller.
Here is the emberjs fiddle for the same: http://emberjs.jsbin.com/rajojufibesa/1/edit
Hope this helps!
I expanded on ViRa's answer.
This code below will allow your components to be passed data with different property keys on the controller. For instance, if the controller has a property data or wants to use the model from the router, the property key does not matter. The component does not need to have a fixed property key that is always used on the controller, such as "foo", instead it will dynamically find it.
didInsertElement: function() {
var controller = this.get('targetObject');
// Find the key on the controller for the data passed to this component
// See http://stackoverflow.com/a/9907509/2578205
var propertyKey;
var data = this.get('data');
for ( var prop in controller ) {
if ( controller.hasOwnProperty( prop ) ) {
if ( controller[ prop ] === data ) {
propertyKey = prop;
break;
}
}
}
if (Ember.isEmpty(propertyKey)) {
console.log('Could not find propertyKey', data);
} else {
console.log('Found key!', propertyKey, data);
controller.addObserver(propertyKey, this, this.onDataChange);
}
}
Update: Here is a JSBin: http://emberjs.jsbin.com/nafapo/edit?console,output
What is the difference between .create() and .createWithMixins()? I am not able to find any documentation regarding this. When I create a view instance using .create() and call this._super() in the didInsertElement method then, following error is thrown:
Ember.Object.create no longer supports defining methods that call
_super.
But, when I replace .create() with .createWithMixins() everything works fine. Here is the code and the sample js fiddle :
App.SampleView = Ember.View.create({
sampleProperty : "a",
didInsertElement : function(){
this._super();
this.set("sampleProperty", "b");
}
});
http://jsfiddle.net/bErRT/3/.
From Wikipedia:
In object-oriented programming languages, a mixin is a class, which
contains a combination of methods from other classes. How such
combination is done depends on language, but it is not by inheritance.
If a combination contains all methods of combined classes it is
equivalent to multiple inheritance.
In Ember instances of objects are created with the create method with no arguments, or with a single hash(kvo) that represent the properties of that type, and they will be automatically populated. Example:
var SomeClass = Ember.Object.extend({
name: '',
url: ''
});
// this instance will have a "name" and a "url" properties with blank values
var someInstance = SomeClass.create();
// this instance will have the same properties, but now
// their values will be populated
var anotherInstance = SomeClass.create({
name: 'Ember.js',
url: 'http://emberjs.com'
})
On the other hand, crateWithMixins, allow you to mix another class definition into a single object instance or into another class. So let's say you have the same SomeClass above, but you don't want to sub-class it via extend and create another type. In this case you can use a Mixin to make sure that only that one instance will have that definition of the two classes. Example:
var SomeClass = Ember.Object.extend({
name: '',
url: ''
});
// note that you don't extend a mixin, you only create
var SomeOtherClass = Ember.Mixin.create({
doSomething: function() {
console.log('doing my thing');
}
});
// This instance will have a method called "doSomething"
var x = SomeClass.createWithMixins(SomeOtherClass, {
name: 'Ember.js',
url: 'http://emberjs.com'
});
// this instance only has methods/properties defined in "SomeClass"
// therefore, no method called "doSomething"
var y = SomeClass.create({
name: 'Google',
url: 'http://google.ca'
});
However, if you want to create a new class with a Mixin, you can extend Em.Object, passing the Mixin as the first argument, as follows:
var AnotherClass = Ember.Object.extend(SomeOtherClass, {
firstName: '',
lastName: ''
});
var z = AnotherClass.create();
z.set('firstName', 'Hiro');
z.set('lastName', 'Nakamura');
z.doSomething();
Check out the API Documentation as well as this JSFiddle.
Edit: As for _super(), you only use this when you create a new class (via extend). When you create instances of existing classes, you shouldn't call _super().
Another thing. I see you're trying to create a View directly. I believe, based on your code, you should be extending Ember.View and let the framework create instance for your at the appropriate time. If you create manually, you'll be responsible for some parts of its workflow like appending it to the DOM, removing it, etc. Maybe I don't see the whole picture, but based on this code alone, I think you should not call create there and call extend instead, and then you'll be able to call _super()