Listing Form Templates within another Controller view - cakephp

I have a form_templates table and a forms table. They're connected by form_template_id. I want to be able to list the form_templates that have been created by title within a select.ctp file I have created within the Forms controller. Just wanting some direction on how to do this with cakephp?
At the moment I have the following code within my FormsController:
public function select()
{
$this->set('page_heading', 'Current Forms');
$contain = [];
$formTemplate = $this->FormTemplates->Forms->find('list', ['order' => 'title'])->where(['active'=>true]);
$forms = $this->paginate($this->Forms->FormTemplates);
$this->set(compact('forms', 'formTemplate'));
}
But I am getting a Call to a member function find() on null error.
Any help on how to tackle this would be greatly appreciated. I know it would be simple but I am new to cakephp.

In your FormsController only FormsTable is loaded automatically, and you are trying to access model that is not currently loaded:
$formTemplate = $this->FormTemplates->Forms->find(...
To get what you want, you should access associated FormTemplatesTable like this:
$formTemplate = $this->Forms->FormTemplates->find(...

Related

How do I delete objects within objects in Angular-Meteor?

NOTE: the following code and demo are extracted from a larger Meteor + Angular project.
I have the following functions to select and delete objects:
DEMO: http://plnkr.co/edit/Qi8nIPEd2aeXOzmVR6By?p=preview
$scope.selectParty = function(party) {
$scope.party = party;
$scope.type = party.type;
$scope.date = party.date;
}
$scope.deletParty = function(party) {
$scope.parties.remove(party);
}
$scope.selectOrganizer = function(organizer) {
$scope.organizer = organizer;
$scope.name = organizer.name;
$scope.title = organizer.title;
}
$scope.deletOrganizer = function(organizer) {
$scope.party.organizers.remove(organizer);
}
The Select action works on both Parties and Organizers as you can see in the demo, displaying the data in the table underneath.
The Delete action doesn't work. Although, let me point out that in my app, the one I have on my machine and currently working on in Meteor, the Delete action works splendidly on Parties, meaning the syntax "$scope.parties.remove(party)" works. But it doesn't work on the plnkr demo for some reason :(
My question is really about the Organizers Delete action, where I'm targeting an object (organizer) inside an array inside the selected object (party)… that one doesn't work. I'm wondering why, and what is the right syntax.
NOTE 2: I'm aware of Angular's splice and index but I can't use them here as I'm not simply working with Angular arrays but with database data in Meteor.
Thanks!
The organizer is a part of the party object and not a collection on it's own. So what you would need to do is remove the party from the object and then save the party object.
Note2 is incorrect. Unless you wrote your question and plunker wrong.

How to get Entry Id for a Newly Created Entity in Breeze

i want to create a registration form that will be in batch with a continuation button, getting the id of the entry will help me to call the save method.
I want to immediately get the primary key of a new Entry Created using BreezeJS, Pls i need help on this.
Thanks
Not entirely sure I understand your question, but it sounds like you want to get the id of a newly saved record immediately after the save. If so then the answer below applies.
When the save promise resolves it returns both the list of saved entities as well as a keyMappings array for any entities whose ids changed as a result of the save. i.e. a mapping from temporary to real ids. i.e. (Documented here: http://www.breezejs.com/sites/all/apidocs/classes/EntityManager.html#method_saveChanges)
myEntityManager.saveChanges().then(function (saveResult) {
// entities is an array of entities that were just saved.
var entitites = saveResult.entities;
var keyMappings = saveResult.keyMappings;
keyMappings.forEach(function(km) {
var tempId = km.tempValue;
var newId = km.realValue;
});
});
On the other hand if you have an entity and you just want its 'key' you can use the EntityAspect.getKey method. (see http://www.breezejs.com/sites/all/apidocs/classes/EntityAspect.html#method_getKey)
// assume order is an order entity attached to an EntityManager.
var entityKey = order.entityAspect.getKey();

Difference in accessing variables in views

I've two controllers one is "Upload" which deals with images uploads and other is "Page" whid deals with the creation of pages of CMS now if in my "Upload" controller I load both the models i.e 'image_m' which deals with image upload and "page_m" which deals with the pages creation I've highlighted the relevant code my problem is if I access the variables in the view
$this->data['images'] = $this->image_m->get(); sent by this I can access in foreach loop as "$images->image_title, $images->image_path" etc
But the variable sent by this line ***$this->data['get_with_images'] = $this->page_m->get_no_parents();*** as $get_with_images->page_name, $get_with_images->page_id etc produces given error
A PHP Error was encountered
Severity: Notice
Message: Trying to get property of non-object
Filename: upload/index.php
Line Number: 20
what is the difference between these two access levels one for $image & other for $get_with_images because I can only access its values as $get_with_images
class Upload extends Admin_Controller {
public function __construct() {
parent::__construct();
***$this->load->model('image_m');
$this->load->model('page_m');***
}
public function index($id = NULL) {
//var_dump($this->data['images'] = $this->image_m->get_with_images());
//$this->data['images'] = $this->image_m->get_with_images();
***$this->data['images'] = $this->image_m->get();***
$this->data['subview'] = 'admin/upload/index';
if ($id) {
$this->data['image'] = $this->image_m->get($id);
count($this->data['image']) || $this->data['errors'][] = 'Page Could not be found';
}
$id == NULL || $this->data['image'] = $this->image_m->get($id);
/*this calls the page_m model function to load all the pages from pages table*/
***$this->data['get_with_images'] = $this->page_m->get_no_parents();***
You are not posting all your code so its hard to tell but is it because you used $this-> in the controller, but you haven't done the same thing in the view?
In this case i would recommend not using $this-> because its not necessary. Also its much better to check for errors etc when you call the model so do something like
if ( ! $data['images'] = $this->image_m->get($id) ) {
// Failure -- show an appropriate view for not getting any images
// am showing $data in case you have other values that are getting passed
$this->load->view( 'sadview', $data ); }
else {
// Success -- show a view to display images
$this->load->view( 'awesomeview', $data ); }
so we are saying if nothing came back - the ! is a negative - then show the failure view. Else $data['images'] came back, and it will be passed to the view. note i have not had to use $this-> for anything and it won't be needed in the view.
Would also suggest using separate methods - have one method to show all images and a separate method like returnimage($id) to show an image based on a specific validated $id.
====== Edit
You can access as many models as you want and pass that data to the View. You have a different issue - the problem is that you are waiting until the View to find out - and then it makes it more difficult to figure out what is wrong.
Look at this page and make sure you understand the differences between query results
http://ellislab.com/codeigniter/user-guide/database/results.html
When you have problems like this the first thing to do is make a simple view, and echo out directly from the model method that is giving you problems. Its probably something very simple but you are having to look through so much code that its difficult to discover.
The next thing is that for every method you write, you need to ask yourself 'what if it doesn't return anything?' and then deal with those conditions as part of your code. Always validate any input coming in to your methods (even links) and always have fallbacks for any method connecting to a database.
On your view do a var_dump($get_with_images) The error being given is that you are trying to use/access $get_with_images as an object but it is not an object.
or better yet on your controller do a
echo '<pre>';
var_dump($this->page_m->get_no_parents());
exit();
maybe your model is not returning anything or is returning something but the data is not an object , maybe an array of object that you still need to loop through in some cases.

Knockoutjs how to data-bind observable array members based on IDs

I'm not if the title explains what I need to achieve or not but I can change it later if some has a better suggestion.
I'm using KO to manage a whole bunch of data on the client side.
Here's the basic.
I have a list of training sessions
Each has a list of training session parts
Each training session parts are referencing items kept in other lists. For example, I have a list of activities (ex: biking, running, swimming, etc.)
Each activity is identified by an ID which is used in the training session parts to identify which activity was used for a particular session.
Now, all these list are stored as observable arrays, and each member of the lists are observables (I use KO.Mapping to map the JSON coming from the server)
When I display a training session in my UI, I want to display various information coming from various lists
Duration: 1h30
Activity: Biking
Process: Intervals
The only information I have in order to link the training session to its component is an ID which is fine. What I'm not sure is how to data-bind the name (text) of my activity to a <p> or <div> so that the name will change if I edit the activity (by using some functionality of the application).
The training session only has the ID to identify the activity, so I don’t know how to bind the name of the activity based on its ID.
Hopefully this makes senses and someone can help me figure it out. I found lots of info on how to bind to observable array but nothing addressing ID and linked information.
The easiest way would probably be to make your own constructors and link the data by hand. You can use mapping if you really want to, but you'll basically have to do the same manual linking, only in a more verbose format.
This is the fiddle with the example implementation: http://jsfiddle.net/aKpS9/3/
The most important part of the code is the linking, you have to take care to create the activity objects only once, and use the same objects everywhere, as opposed to creating new activity objects for the parts.
var TrainingSession = function(rawData, actualActivities){
var self = this;
self.name = ko.observable(rawData.name);
self.parts = ko.observableArray(ko.utils.arrayMap(rawData.parts, function(rawPart){
return ko.utils.arrayFirst(actualActivities(), function(ac){
return ac.ID() == rawPart.ID;
})
}));
}
var Activity = function(rawData){
var self = this;
self.ID = ko.observable(rawData.ID);
self.name = ko.observable(rawData.name);
}
var MainVM = function(rawData){
var self = this;
//first create an array of all activities
self.activities = ko.observableArray(ko.utils.arrayMap(rawData.activities, function(rawAc){
return new Activity(rawAc);
}));
self.trainingSessions = ko.observableArray(ko.utils.arrayMap(rawData.trainingSessions, function(session){
return new TrainingSession(session, self.activities);
}));
}

Adding a 1 to many file upload to CRUD

My app has sales listing functionality that will allow the user to add 1 or more photos for the product that they want to sell.
I'm attempting to use the upload/filestore_image of ATK with a Join table to create the relationship - my models:
class Model_Listing extends Model_Table {
public $entity_code='listing';
function init(){
parent::init();
$this->addField('name');
$this->addField('body')->type('text');
$this->addField('status');
$this->addField('showStatus')->calculated(true);
}
function calculate_showStatus(){
return ($this->status == 1) ? "Sold" : "For Sale" ;
}
}
class Model_listingimages extends Model_Table {
public $entity_code='listing_images';
function init(){
parent::init();
$this->addField('listing_id')->refModel('Model_Listing');
$this->addField('filestore_image_id')->refModel('Model_Filestore_Image');
}
}
In my page manager class I have added the file upload to the crud:
class page_manager extends Page {
function init(){
parent::init();
$tabs=$this->add('Tabs');
$s = $tabs->addTab('Sales')->add('CRUD');
$s->setModel('Listing',array('name','body','status'),array('name','status'));
if ($s->form) {
$f = $s->form;
$f->addField('upload','Add Photos')->setModel('Filestore_Image');
$f->add('FileGrid')->setModel('Filestore_Image');
}
}
}
My questions:
I am getting a "Unable to include FileGrid.php" error - I want the user to be able to see the images that they have uploaded and hoped that this would be the best way to do so - by adding the file grid to bottom of the form. - EDIT - ignore this question, I created a FileGrid class based on the code in the example link below - that fixed the issue.
How do I make the association between the CRUD form so that a submit will save the uploaded files and create entries in the join table?
I have installed the latest release of ATK4, added the 4 filestore tables to the db and referenced the following page in the documentation http://codepad.agiletoolkit.org/image
TIA
PG
By creating model based on Filestore_File
You need to specify a proper model. By proper I mean:
It must be extending Model_Filestore_File
It must have MasterField set to link it with your entry
In this case, however you must know the referenced ID when the images are being uploaded, so it won't work if you upload image before creating record. Just to give you idea the code would look
$mymodel=$this->add('Model_listingimages');
$mymodel->setMasterField('listing_id',$listing_id);
$upload_field->setModel($mymodel);
$upload_field->allowMultiple();
This way all the images uploaded through the field will automatically be associated with your listing. You will need to inherit model from Model_Filestore_File. The Model_Filestore_Image is a really great example which you can use. You should add related entity (join) and define fields in that table.
There is other way too:
By doing some extra work in linking images
When form is submitted, you can retrieve list of file IDs by simply getting them.
$form->get('add_photos')
Inside form submission handler you can perform some manual insertion into listingimages.
$form->onSubmit(function($form) uses($listing_id){
$photos = explode(',',$form->get('add_photos'));
$m=$form->add('Model_listingimages');
foreach($photos as $photo_id){
$m->unloadDdata()->set('listing_id',$listing_id)
->set('filestore_image_id',$photo_id)->update();
}
}); // I'm not sure if this will be called by CRUD, which has
// it's own form submit handler, but give it a try.
You must be careful, through, if you use global model inside the upload field without restrictions, then user can access or delete images uploaded by other users. If you use file model with MVCGrid you should see what files they can theoretically get access to. That's normal and that's why I recommend using the first method described above.
NOTE: you should not use spaces in file name, 2nd argument to addField, it breaks javascript.

Resources