I have a controller/view. (Section.item) that take...
# fw1
m
I have a controller/view. (Section.item) that takes one primary key I’d and renders the instruction for that item. Works perfectly. Now, I am attempting to add a new section.item is same section to take user input of more than one primary id but was hoping to call the controller from this new view looping over list of ids and cannot figure out how to implement. Controller () cannot be called from view and calling the view only does not take new parameters into account. I know this is no code but maybe I need fresh eyes to tell me use fooBar dummy? Looking for ideas. Anyone got any for me?
c
Are you looking to add a different "item" view for when multiple IDs are passed in, but still have it handled by the same controller method "item"?
m
Yes. Add a new item (controller function and view) to loop over multiple ids. But thought I could use the existing item to reuse the formatted output. View is about 1200 lines of code and new addition is to have N ids using same formatting to go to PDF ultimately.
c
You can't have two methods with the same name, but you can use one method to examine the RC content, and use conditional logic to render one or the other views. So your item method could look something like this pseudocode:
Copy code
public void function item (rc) {
    if rc.keyExists('keyId') {
        view( 'item' );
    }
    if rc.keyExists( 'keyIds' ) {
        view( 'multipleitems' );
    }
...
}
Then you put the code for multiple ids in a view file called 'multipleitems.cfm'.
c
I know you said that's pseudocode, but I think you'd want
setView()
rather than
view()
. Plus you'll need a reference to the framework in the controller. And the first condition isn't needed because "item" is the default view for that action.
Copy code
// make the FW/1 API available to this controller
public function init( fw ) {
  variables.framework = fw;
  return this;
}

public function item( rc ){
  if( rc.KeyExists( "keyIds" )
    variables.framework.setView( "multipleItems" );
}
m
@cfvonner & @cfsimplicity Thank you both for your comments. So to use code to display what I am attempting to do.
Copy code
// make the FW/1 API available to this controller
public function init( fw ) {
  variables.framework = fw;
  return this;
}

public function ShowOneItem( rc ){
  // user input checked and calls to DBs with rc.keyID
}
public function ShowMultiple( rc ){
  // user input checked and with rc.keyIDs
  // I was hoping to call the ShowOneItem from LOOP within ShowMultiple view where the ShowOneItem
}
I have tried to place HTML output into savecontent variable, I was even thinking of CFHTTP but that seems like a bridge too far. I am not sure if that helps to clarify. But at this point, I am thinking this might not be possible.
c
It sounds like you want the opposite of what was suggested: 2 different actions using a single view (rather than one action and 2 different views)? In which case the
view()
method may be what you need after all. You can pass parameters to it as a struct in the second argument and it will return the output as a variable to your controller. https://framework-one.github.io/documentation/4.3/reference-manual/#public-string-function-view-string-path-struct-args----any-missingview----
m
@cfsimplicity that is what initial thought as well, but the Controller for the ShowOneItem() has the calls to the DB to get that data to render in the view. so the view of the ShowMultiple() needs to call the controller ShowOneItem() in a loop and display the view for each time around the loop. I am still back to the fact that this MAY not be able to be done. Was trying to save repeating code but it seems like that is my only option. Thank you for your suggestions.
c
This may be an opportunity to refactor the giant "view" into smaller pieces. Take the piece that displays a single item and put it in it's own .cfm file (when I used FW/1, I'd put a "partials" folder inside my "views" folder for these pieces). Then in your main view .cfm file, loop over the data and call
view( arguments )
for each item. Then, rather than looping in your controller, pull all of the data in one call to the database, pass it all to the main view, and loop over it inside of the view.
@cfsimplicity you are correct re:
view()
vs.
setView()
. Toward the end of the time I was using FW/1, I was using
view()
with arguments almost exclusively, so I forgot about
setView()
.
@Matt I think the recommended approach for FW/1 (and indeed any MVC) is to have "thin" controllers and "fat" models. Put as little logic into controllers as is required to pull or process data in the model, and then pass off the results to your view for display. So try to put the logic of retrieving multiple records (when multiple IDs are passed in) in the model, perhaps by a dedicated method in your service cfc.
m
I would have your controller functions call a service for the data, could be the same service if you wish, I would just structure the data the same. Assuming it is returning as an array or a query, then you just loop over it in the view, could be a loop of one or many, doesn't really matter. then they can both use the same view.
m
@Matt Jones & @cfvonner I understand what you are both saying and I will work it out. Your suggestion have helped me. I will follow up after I have implemented my solution.