Controller logic in Element View in CakePHP - cakephp

I'm working on a really big project. The aspect I'm currently working on requires that email templates are sent to a user when they're added to a learning course by another user.
The controller that deals with the request, does a bunch of str_replace tasks to find variables in the text (which the user can edit before adding another user to the learning course) and then replaces it with some values in the DB.
I took over this project and I'm not happy with the way half the things are done but time costs dictate I rather just go along with it.
The email is sent using Cake's native email function. It uses a template to capture data and send to the user.
Here's the question:
Should I keep the logic in the controller or do you think it's safe to move it to the element view's .ctp file?
My first instinct is to leave it in the controller as per the usual MVC separation ideals.
Cheers

This is a very important question - what are you using exactly for the email? The old email component or the new CakeEmail class? Which CakePHP core version are you using?
Here are some plausible aproaches here. You can:
Set all those variables, pass them to the view and do all the "replacing" there.
Encapsulate this logic in a component, attach it to your controller(s) and use it.
Just leave it in a private function within the controller and call that function whenever needed. (not really MVC)

Related

How to isolate form's logic in Angular

Sometimes forms has some logic: some additional data requested with ajax, it reads cookie or has a special filter. I would like to separate this logic from controller. I also would like to have forms' html in a separate file. How to achieve this?
Is it possible to make factory or service work with form?
I have an idea about implementing each form as directive. Would it be good solution?
EDIT:
The main goal is not to move HTML to separate file but to move the form logic out of main route controller. Is it possible to write some provider that takes care of the form so that all data queries for the form select elements (and other logic) is happening in this provider and it calls controller's function just at the end to save validated data?
I also would like to have forms' html in a separate file. How to achive this?
You can use ready made directives like ng-include to include external HTML fragments, or you can have your own template-expanding directive.
Is it possible to make factory or service work with form?
You can create any provider whose operation is dedicated to handle form(s). This is your model than an angular technique.
I have an idea about implementing each form as directive. Would it be good solution?
If you have many forms in your application and they are playing a pivotal role, yes - having directives for forms could be termed as a specific solution. The pros and cons cannot be explicitly judged here since the rest of the application's character is unknown.
Probably this is one of the places you should start your research from.
Your question is too broad. If you would like to separate the form from the controller, you need to put that form into a directive, which would allow you to put the html and javascript for the form in a separate file.
Another way to put the form html in a separate file is to use ng-include, however, this simply lets you move the html, whereas the first method will allow you to have a separate controller for the form html.
I have an idea about implementing each form as directive. Would it be good solution?
I believe that is THE solution you are looking for.

Using 2 views and sharing data in AngularJS

Im trying to share data between 2 views. I need to use the 2 views at the same time on two different machines. One is controlling the other(ex: a counter) 1st view has next(+1) and the other just displays the result. I want the data to synchronized/binded. I do not want to have to refresh the 2nd page or to have to pull data with a timer or otherwise.
My idea was to use ng-view and routeProvider, I know that when the view changes the scope is cleared so I tried to use a parent controller/scope, the data is shared but I have to refresh the page on my 2nd view. I tried a service, same thing. I tried to $watch the result of the service but on the second controller/view no event is picked up so the view doesn't update.
what is the way to go? I was thinking about broadcasting or emit a custom event and trying to catch it, will that work? Am I just not binding to the service correctly? Would ui-router work better? I feel there should be an easy way to do this.... Im not seeing it! Please help if you can.
One of the simplest (in my opinion) implementations of client-client communication is using WebSockets. While that does have compatibility limitations (some browsers), that can easily be overcome by using a library like socket.io. Also, it's easy to write an Angular wrapper/service over socket.io that can be shared across components of your app, or even different modules.
It's also pretty simple to write a Node backend with socket.io
This might be a good read.
I would suggest you to focus on pushing stream rather than sharing it. Some how you need to push stream to second view which is changes in first view.
You may want to check this
Is there some way to PUSH data from web server to browser?

Angular ui-router nested views don't refresh data retrieved by Angular Services

I have a nontrivial Angular SPA that uses ui-router to manage multiple views, many of which are visible at the same time. I need models to be visible across controllers, so I have services written that allow me to have controllers pull down fresh copies of model data that has been updated.
I apologize in advance for the length of the question, but I will state the problem then state what I have done to address issues I'm sure others in the Angular community have struggled with.
I believe my problem is not understanding the lifecycle of controllers / views, because I get behavior where a controller initializes correctly the first time I go there, but then seems to never run again, even when I navigate to it using something like $state.go("state name").
In one view (contrived example), I show a summary of information about a customer, and in another view I allow a user to update that customer's more detailed profile. I want a user to edit, say, the customer last name in the detailed view, and have the summary view automatically recognize the change and display it.
I have a fiddle that shows 3 views and a simple password changing Service. The flow goes like this:
You can see each view gets initialized and displays the initial password retrieved from the service. All views are in sync with the DataService.
The middle view allows you to enter a new password and change the one stored in the service. Console logging confirms that the service picks up the new password just like you would expect.
(odd behavior #1) When the DataService receives the new password, I would expect the other 2 views (top and bottom) to display the new one. They don't... they still display the initial password.
There is a button to allow a user to go to another state via $state.go("state name") (a child state of the original) which also retrieves the password and displays it. This works the first time (see #5). Now the top view shows the outdated password, the middle view shows the new one, and the bottom one shows the new one as well. This seems normal, since the new view is invoked after the DataService contains a new password value.
(odd behavior #2) If I click back in the middle view and change the password again, and click the button to change states again, the bottom view (which updated just fine in step #4) no longer updates its copy of the password. Now all 3 views show different passwords, even though I am using a single service to pass values between controllers as suggested pretty much everywhere you look for Angular best practices.
Some possible solutions:
Tim Kindberg has an excellent slideshow here that seems to recommend using ui-router's state heirarchy to "pass" data among views that need to pick up values from other views. For a smaller-scale app I think I would settle on this, but I expect our application to have 30+ views displaying data from over 100 REST endpoints. I don't feel comfortable maintaining an application where all the data is being shared by a complex inheiritance tree. Especially using a routing framework that is at version 0.2.8.
I can use events to have controllers listen for changes in the data model. This actually works well. To accommodate performance concerns, I am using $rootScope.emit() and a $scope.$onRootScope('event name') decorator I found on here. With this approach I am less concerned about event performance than I am about wiring this huge app with a bunch of event listeners tying everything together. There is a question about the wisdom of wiring a large app using angular events here.
Using $watch on the value in the DataService? I have not tried this but I am hesitant to hinge an app this size on hundreds of $watches for performances reasons.
A third-party library like bacon.js (or any of a dozen others) that may simplify the event spaghetti, or create observable models that my controllers can watch without the risk of $digestageddon. Of course, if there is a concise way to handle my issue using Angular, I'd prefer not to muddy the app with 3rd party dependencies.
Something that lets controllers actually reference .service modules by reference, so I don't have to depend on tons of event wiring, complex state hierarchies, 3rd party libraries, or seeding the app with hundreds of $watches and then kicking off $digests to update controllers' references to Angular services?
Some solution that relies on time-tested OO and design patterns and not a 3rd-party library or framework that has a version that starts with 0.*.
Thanks in advance... I appreciate the help!
This is no problem of ui.router. If you intend for your model (your data service) to be a single source of truth, you have to refrain from destroying it.. err.. the reference to it that is. And in your case, assigning a primitve (a string) directly to the scope, instead of a reference to it. In other words...
var password = {pw:'initial value'};
and then later setting/binding only on
password.pw = newpassword
{{password.pw}}
Heres a fiddle. And also here is a short little read on scopes, It also includes a video of an angular meetup where Misko talks about "always have(ing) a dot in your model" link and how the $scope is a place to expose your model, not be your model. (aka not a place to assign primitives like password = 'initial value')
Hope this helps!
try remove the animation property of your ion nav view.
remove the property
animation="slide-left-right"
it would be ok.

mvc programming question

Am using a view file,controller and a helper. am accessing data value through webserver.
Steps:
the controller get value from webserver and set it in the view. the view uses the helper to display the data in some format. But my helper again calls the webserver method to get the inner values. Is it correct the helper accessing webservice method? Is it the correct way of programming in mvc?
Thanks,
IMO, a webservice is just another datasource and should be accessed via the model. If it's me, I handle it by either creating a new model for the service call (if the service call is in support of an existing entity, it may make more sense to make the call in that entity's model itself). My controller calls the model method, sends the data to my view which, in turn, forwards that data on to the helper.
This maintains the MVC separation, but still allows the data you need to make it's way into the helper where you need it.
I will tell you what is written in the Ruby on Rails book. I can not remember the title right now but...
Helpers are usually used for view rendering not for server calls.
Hope it helps.

Making a drupal database call using ajax

I want a link that when you click on it, it will call a simple ajax query which updates a database entry. Normally this would be easy, but because authentication needs to happen before the query is executed, I need to be able to execute the Ajax Query AS THE CURRENTLY LOGGED IN USER. I.e. I need access to the $user variable and I don't want to create a new connection.
Does Drupal have native functions that can do this? Is there something I can use to do this?
You're going to want to create a module to handle this. Then, whatever function you call through the callback will have complete awareness of the logged in user.
Keep in mind that if someone makes a link that goes to your AJAX destination on their website, and can trick people into clicking it (or, for that matter, makes that link the src on an img tag), then weird things can happen to people's data without them meaning to.
I suggest the use of a token and checking that the token submitted as part of the link matches something to do with the user. Check drupal_get_token() for a good way to generate one.
Either create a menu item in a module implementing hook_menu() and specify a callback to a function handling this request - or use the Services module and create a new service module.

Resources