How to implement a helper in Symfony 1.4? - symfony1

I'd like to create my own helper but can't find any help on Google for Symfony 1.4/Doctrine.
I guess it has something to do with creating a myClassHelper.class.php in lib/helpers/ or something, but I don't know what to implement, or if specific methods have to be overridden.
Any help would be appreciated!

I don't think that anything changed regarding the helpers in 1.4. From the documentation(although 1.2):
Helper functions (regular PHP functions returning HTML code) should be saved in a file called FooBarHelper.php, where FooBar is the name of the helper group. Store the file in the apps/myapp/lib/helper/ directory (or in any helper/ directory created under one of the lib/ folders of your project) so it can be found automatically by the use_helper('FooBar') helper for inclusion.
So you just put normal functions in a normal file (has nothing to do with classes or methods). The functions can take arbitrary parameters (you decide what they need to create the HTML) and the have to return HTML.
E.g.
MyHelper.php
function hello_word() {
return '<strong>Hello world!</strong>';
}
and in the template:
<?php use_helper('My') ?>
<!-- somewhere in the template -->
<?php echo hello_world() ?>

Related

Can I make a partial template that have readonly fields when used by show and not when used by edit and create?

I've partial templates that are used by the show, edit and create form.
In the show-form I don't want them editable, it can be confusing for the user.
Is there a simple solution for this otherwise I need a different template for the show-form or... why use a template then.
I've tied this and created 2 scripts, one that disables and one that enables.
Script 1.
$(document).ready(function(){
$('.elements').attr('readonly',true);
$('.elements').prop('disabled',true);
});
Script 2.
$(document).ready(function(){
$('.elements').attr('readonly',false);
$('.elements').prop('disabled',false);
});
Then I stored those scripts in assets\javascript.
It worked good in show but both edit and create went read-only too.
It seems like everything that is put in this directory is automatically used in each form, because even though I removed the call from the forms, it was working.
Here I show where I originally added the script-call:
<asset:javascript src="myScript_1.js"/>
</body>
</html>
I was going to add it as a comment but then it started to get long and complicated to follow.
why store it in assets ?
simply add a function block to the templates that need it
_template1.gsp
<script>
$(document).ready(function(){
setReadOnly('${someDefinition}')
function setReadOnly(value) {
if (value==='READONLY') {
$('.elements').attr('readonly',true).prop('disabled',true);
}
}
})
</script>
If this function needs to be shared by a bunch of pages, you could add it to an assets / javascript file but rather than declare it in application.js call the js file <asset:javascript tags specificially on each page
and maybe a variable that you pass to template to say when it should be called
or put that above template1 as a master template and call in each of the other templates that needs the js file (So many options)
Now on the main controller doing action
def MyController {
def view() {
String mode='READONLY'
render view: 'index', model:[instance:params,mode:mode]
}
}
the in index.gsp
if js is there then it will pick up mode and set readonly for that controller action or pass that from one template to another, the controller does not have to define actual mode, the main master view page or index page could define mode too
Maybe you need to play/understand then implement you can't rush these things otherwise you will end up wasting time and rewriting
Just to ensure we are on the same page.
By default the application.js file in the javascript folder has a tree line enabled - this by default then reads in all js files. If you wish to manually call js in different places you will need to remove this line and declare each and every js file that you use like the other lines provided in that file.
So that is the price to pay (no more auto loading js files) until declared in application.js
But then most importantly as you have noticed these are global js functions and really nothing new should be going in there that hasn't got a function something() { } a function call.
They will then react when the actual function is called rather than how you had it which was open for call from any old page since it happened as documents opened regardless

Using components in admin-generator modules, it's possible? how?

I need to build a admin interface like this image show. In the past I use components for that purpose but now because the modules are generated trough admin-generator I don't know how to get this done. I check all this docs 1, 2, 3 but without any clue on how to do this. I also created a components.class.php under modules/sdriving_empresa/actions folder and include the component in the view include_component('sdriving_empresa') but get this error:
sfComponents initialization failed.
Any help?
Tabs and Partials, the easy way :)
One of the best possible javascripts for that purpose is Javascript Tabifier. Its easy
to install and play with it. You will find a lot of other Javascript and jQuery Tabbers, get the one you most like.
I would advise you to learn everything about symfony 1 partials in order to get the job easily done. Usually partials are a piece of code which is saved in an external file, and does is loaded later in any part of your code. Its like a variable with a lot of html and php code. Partials (the external files) allow also to receive input variables, so its easy to send them ids from related modules or tables.
Lets look at an example with Tabifier with two Tabs, information and Admin and two partials
editSuccess.php
$sModuleName = sfContext::getInstance()->getModuleName();
$sbasepathtabs = $sModuleName . '/tabs';
<div class='tabber' id='tabberglobal1'>
<div class='tabbertab' title='Information' >
<?php
include_partial($sbasepathtabs . '/_information/_information', array('form' => $form));
?>
</div>
<div class="tabbertab" title="Admin" >
<?php
include_partial($sbasepathtabs . '/_admin/_admin', array('form' => $form));
?>
</div>
</div>
Easily setup it:
Inside your module template folder, create the folder: /_tabs
Inside the folder /_tabs create the folder /_information and /_admin
Inside the folder /_tabs/_information create the file partial: _information.php
Inside the folder /_tabs/_admin create the file partial: _admin.php
Inside each one of those files partials write anything you want.
Those partials will receive the left variable form: array('form' => $form).
You can send to the partials more than one variable: array('form' => $form, 'variable2' => $formnumber2)
When you write a partial, in example the partial _information, you can easily get the form object and its values in the template with:
$id = $form->getObject()->getId();
For normal variables you wont need to call getObject.
Finally, take a deep look at the documentation of both things, symfony partials and Javascript Tabifier. They will solve you anything you need.
Backend Admin Generator:
Admin generator automatically generates all templates in the cache folder. Example:
cache\backend\prod\modules\autoTbPrueba1Backend\templates
cache\backend\prod\modules\autoTbPrueba1Backend\templates\indexSuccess.php
Most of its files are already partials, pay attention to the files who has the _ symbol in their name, they are partials. This means that most of the work is already done for you, and the only thing you will have to do is to override some of the partials (TbPrueba1Backend/list_header which is the file _list_header.php) or even the full template (indexSuccess.php) with the extended information you need.
In order to override backend generated templates and partials, you can copy those files to the template folder of your module:
apps\backend\modules\TbPrueba1Backend\templates
apps\backend\modules\TbPrueba1Backend\templates\indexSuccess.php
Set there any additional information you need, and if you dont see anything new while refreshing the web, remember to clear the symfony cache (symfony cc).
Once you have override the the templates and partials with the new information, the only thing you need now is to write/add those partials inside the div tabs created by your bootstrap framework as I described above.
For a good explanation of the admin generator:
Symfony 1.4 change admin generator actions or templates
http://www.slideshare.net/loalf/symfony-y-admin-generator
http://symfony.com/legacy/doc/jobeet/1_4/en/12?orm=Doctrine
You need the moduleName and the componentName in your include_component()
function include_component($moduleName, $componentName, $vars = array())
{
echo get_component($moduleName, $componentName, $vars);
}
Or maybe your module is in the wrong application. In that case, you may consider moving it in a plugin

How to separate javascript libraries and calls in the Rails 3.1 asset pipeline

I'm trying to get the hang of the whole asset pipeline thing, and read the guide and several tutorials about them. But one thing that doesn't become quite clear is wether I should view my javascript asset files as a library or a place to put code that is actually run i.e. $(document).ready. Because by default all the javascript files are included, and it would be weird to have several $(document).ready's in there, not to mention that you don't want the $(document).ready function for every page to be run in the first place. What would be the way to go at this? Use my asset files as a library and put actual calls in my views (ugly)? Or is there a better way to do this?
I too ran into this issue. In a large project you can have somebody put code into document ready to, for example, add a click function to each li within a div with class container.
Now we could all argue that the above code would be too generic and of course may affect li tags in other parts of the application, but the bigger the project, the more likely it is that you will run into a conflict like this leading to unexpected behaviour.
I for one am uncomfortable with a whole bunch of document ready functions running for each and every page loaded. My solution is not necessarily the perfect one, but it's one that I have taken up and will share with you.
In the body tag of each page I add data elements signifying the controller and the action. I then have one document ready script that looks for a class named after the controller with the name Ready appended e.g. HomeReady. It will then call a method on this class (presuming it exists) named after the action. So in your asset coffee file you could write:
class #HomeReady
#index: ->
alert("Hello")
#show: ->
alert("Goodbye")
This allows control right down to the action level. When I came across your question I decided to package this solution into a gem as I have already used it in several projects. You can find it at: https://github.com/intrica/rails_document_ready
If you absolutely don't want a certain piece of initialization code to be run unless the current page is a specific controller/action, then you can try adding an empty element on the page with an id built from that info like "posts_index" using these two helpers:
"#{controller_name}_#{action_name}"
Then in your javascript you can wrap the code inside an if statement that checks for the existence of an element with the appropriate id.
edit: Here's an example of the js partial that I mentioned in the comments.
show.html.haml
= render 'map'
map.html.erb (I normally use haml but it's easier to write js in erb)
<script src='http://www.google.com/jsapi' type='text/javascript'></script>
<script type='text/javascript'>
...
</script>
It's probably not as clean as it could be and it doesn't get the benefits of being part of the asset pipeline but I don't mind because it's only something that gets included on a specific page.

How to localize javascript files in a Struts 2 app

I wrote an Struts 2 application and want to localize it. Now I am using javascript and I would like to put the scripts out of my HTML template to an own javascript file.
When I do it, my s:text tags are not rendered (of course).
Question is how can I localize my javascript files with Struts 2 in a clean way? I would like to avoid to use another technique than the properties files i currently use.
Thanks,
Christian
If you want to stick with your resource bundles back at server, one way possible would be to save your javascript files as .jsp file and serve them with an action so this way your struts tags in your javascript files will get a chance to retrieve the data from server and return the file upon request.
Personally I prefer to keep client messages in javascript files and server messages in resource bundles. This way you can save a .jsp processing IMHO.
You can use a hidden field in your JSP and pass its id to the external JavaScript file and get its value like follows.
In your JSP,
<s:hidden id="warning" value="%{getText('propertyKey')}"/>
(hidden field poplated with the value of the property key in the resource bundle)
Call your external JS method from the same JSP,
<s:a href="%{deleteSelected}">
<img src="<s:url value='/images/delete.gif'/>" border="none"
onclick="javascript:return displayWarning('warning')"/>
</s:a>
In external JavaScript file,
function displayWarning(message) {
var ret = true;
ret = confirm(document.getElementById(message).value);
return ret;
}
<script type="text/javascript">
var mytxt='<s:text name="my.text.prop" />';
alert(mytxt);
</script>
This is also possible, but you cant have them inside a function.You should assign relevant properties to global JS variable at the time of page load. Almost same concept slimier to use hidden variables.

Where should I place code which generates Excel spreadsheet?

I am using spreadsheet gem to generate native Excel file. This is not CSV, XML file. Ordinary Ruby code is used to create the file. The generated Excel file (kept in StringIO) is forwarded to a client using send_data method. I need send_data method because of its parameters like disposition.
The data for the Excel is retrieved in controller method just like for ordinary HTML, JS requests. However I placed the code to generate the spreadsheet in controller protected method. Not in a view as I should.
Is there an elegant solution to above problem compliant with MVC design pattern?
Update: There is no popular and accepted by all solution to above problem but at least I know all possible ideas.
The lib directory is meant as a place for code that isn't strictly part of the MVC structure, but will be needed by multiple models, views, or controllers. It can be brought in with a require when needed.
However, if you only need the code in a single controller, you'd be just as well off putting it into that controller's helper. That way it's auto-loaded and at your fingertips. Plus, it makes sense: it's code to help a specific controller.
Either way, don't leave it in your controller or try to wedge it into your view.
Create an excel library in your lib folder in which you include your xls generation routine as well as a method that overrides ActionController's render method.
In a model that should be rendered as xls implement a method called to_excel method which generates a hash that you can provide to your xls routine.
Doing it this way, you'll get something really "Railsy". In your controller you'll just call
render :xls => #model
i just did this today for my app hope this helps for an excel o/p ; never used any plugin
controller:
def export
pr = Program.find(session[:pr_id])
headers['Content-Type']="application/vnd.ms-excel"
headers['Content-Dispositon']='attachment;filename="report.xls"'
#voucherdatas = Voucherdata.find_all_by_pr_name(pr.pr_name)
end
view: export.html.erb
manager
"reports/voucherdatas", :object =>#voucherdatas %>
routes.rb
map.resources :reports ,:collection =>{:export =>:get}
whereever u want the link give
link_to "Export As Excel", export_reports_url, :popup=>true

Resources