Currently within my Project we are using JSDoc, we have recently started to implement Angular and I want to continue using JSDoc to ensure that all the documentation is within the same place.
I have taken a look at people mainly just saying to use ngDoc but this isn't really a viable option as we will always have separate JavaScript and I ideally would have everything together.
/**
* #author Example <jon.doe#example.com>
* #copyright 2014 Example Ltd. All rights reserved.
*/
(function () {
window.example = window.example || {};
/**
* Example Namespace
* #memberOf example
* #namespace example.angular
*/
window.example.angular = window.example.angular || {};
var exAngular = window.example.angular;
/**
* A Example Angular Bootstrap Module
* #module exampleAngularBootstrap
*/
exAngular.bootstrap = angular.module('exampleAngularBootstrap', [
'ngRoute',
'ngResource',
'ngCookies'
])
.run(function ($http, $cookies) {
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
$http.defaults.headers.common['X-CSRFToken'] = $cookies.csrftoken;
});
})();
Currently this is what I have but am unable to put documentation for the run() any ideas?
I have encountered this issue as well. I am now writing documentation for angularjs codes through jsdoc comments like this:
1.Make a blank .js file with the following comment:
/**
* #namespace angular_module
*/
This will create a separate html in the generated documentation for listing all modules.
2.In javascript files that defines any new angular module, use this kind of comment
/**
* #class angular_module.MyModule
* #memberOf angular_module
*/
This will add an item in the above listing of all angular_modules, as well as creating a separate html page for MyModule, because it is a class.
3.For each angularjs service, use the following comment:
/**
* #function myService
* #memberOf angular_module.MyModule
* #description This is an angularjs service.
*/
This will add an item in the MyModule page for the service. Because it is added as a function, you can write documentation for input parameters using '#param' and return values using '#return'.
4.If I have quite long codes in a controller or directive of MyModule and want to have a separate html file to document it, I will annotate the controller or directive as a class using full path. e.g.
/**
* #class angular_module.MyModule.MyController
*/
In this way, MyController will be listed as one item in MyModule's documentation page.
Then, we can annotate codes within the controller as member functions of MyController.
/**
* #name $scope.aScopeFunction
* #function
* #memberOf angular_module.MyModule.MyController
* #description
*/
In this way, this function's documentation will appear in the html file of MyController's html page. The dot-separated full path string builds the connection.
There are three types of syntaxes for namepath:
Person#say // the instance method named "say."
Person.say // the static method named "say."
Person~say // the inner method named "say."
However, one imperfect point of commenting controller as a class is that a "new" will be found before the controller name in the generated html documentation because it is described as class constructor.
Furthermore, you can define namespaces in order to add a hierarchical structure. For example, you can define a namespace to include all controllers
/**
* #namespace MyApp.Controllers
*/
, and prefix all controller with MyApp.Controllers. You can also define namespaces like MyApp.Product or MyApp.Customer etc.
Although not perfect, I like using jsdoc to document angularjs codes because
It is simple;
The module-controller-function hierarchy are kept;
And it keeps jsdoc's merit that it is a browsable documentation site.
A table style jsdoc stylesheet:
Particularly, I've adapted the default jsdoc stylesheet to a table style like the Java API documentation. It looks clearer.
In Windows, I replace this file: C:\Users\user1\AppData\Roaming\npm\node_modules\jsdoc\templates\default\static\styles with this file https://github.com/gm2008/jsdoc/blob/master/templates/default/static/styles/jsdoc-default.css
That's it.
I have had to go down the route of creating the functions outside of the type above and calling those functions in such things as .run or factories etc.
/**
* #author Example <jon.doe#example.com>
* #copyright 2014 Example Ltd. All rights reserved.
*/
(function () {
window.example = window.example || {};
/**
* Example Namespace
* #memberOf example
* #namespace example.angular
*/
window.example.angular = window.example.angular || {};
var exAngular = window.example.angular;
/**
* My example bootstrap run function
* #param {object} $http {#link http://docs.angularjs.org/api/ng.$http}
* #param {[type]} $cookies {#link http://docs.angularjs.org/api/ngCookies.$cookies}
*/
var runFunction = function ($http, $cookies) {
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
$http.defaults.headers.common['X-CSRFToken'] = $cookies.csrftoken;
};
/**
* A Example Angular Bootstrap Module
* #memberOf example.angular
* #namespace example.angular.bootstrap
* #function bootstrap
* #example
* <div ng-app="exampleAngularBootstrap">
* <div ng-view></div>
* </div>
*/
exAngular.bootstrap = angular.module('exampleAngularBootstrap', [
'ngRoute',
'ngResource',
'ngCookies'
])
.run(runFunction);
})();
Related
I'm writing a custom React hook for forms, and since it will have a deep nested structure, I would like to get autosuggestions using JSDOC comments (and don't know typescript, and also my team works with plain JS). But I have a problem. Everything works as expected until the last nest, where I need to pass data object whose property names are dynamic (these are names for the fields in forms and will be names of data object that hook and custom form component will return to me - so they absolutely must be dynamic) - and these properties must be of type object - whose properties now I will define - only those properties should be then supplied - but the autosuggestion doesn't work as it does not recognize * as 'catch-all'... Anyhow, after hours of trying to make it work, I gave up and decided to post the question here in hope that some of you might know how to make this work (if it's possible at all). In any case, thank you for your time, and you can see my code and example usage bellow:
P.S. I use VS Code and autosuggestions for other fields work great, also it works, as I mentioned, when I name the prop instead of * - but all of my attempts to place dynamic value there have failed...
/**
* #typedef {Object} FormField
* #property {string} initialValue - The initial value of the field
* #property {string} type - The type of the field
* #property {function} validate - The validation function for the field
* #property {string} errorMessage - Error message to display if input is wrong
* ... TODO add more here later ...
*/
/**
* #typedef {Object} Data
* #property {FormField} * - A property with any name, and value of an FormField object {#link FormField}
*/
// The line above this is where the problem is - * is not recognized - when I put any
// other name and I put that name when calling it - autosuggestion works
/**
* #typedef {Object} Item
* #property {string} [title] - The title to display above the input fields - optional
* #property {string} [className] - Class name to give to container for all fields
* #property {Data} data - The data objects specifying just how to create the form. Use
* autosuggestion to properly set it up
*/
/**
* #description A custom hook for handling forms
* #param {Item[]} arr - An array of item objects - from which to create a form
* #return {Object} - Object with form state, data and functions
*/
// Example usage:
const form = useForm([
{
title: 'Test',
className: 'test',
data: {
email: {initialValue: '', type: 'email', validate: value => isValidEmail(value), errorMessage: 'Invalid email address'},
anyNameHere: {} // Should be able to take any name here and give me initialValue, validate and other
// suggestions when I trigger autosuggestions.
}
}
]);
If I get you right, data field may have any key with value FormField, so you can define Data as
/**
* #typedef {Record<string, FormField>} Data
*/
I'm using Cakephp 2.4.3 . I've read that "There are CakePHP plugins that are able to generate sitemaps for you. This way your sitemap.xml file will be created dynamically on demand and will always be up to date." . I've searched but all I find are from old cakephp version which is not useful as they only cause errors .
Is there still a good plugin for this?
Some plugins definitely exist:
https://github.com/sdevore/cakephp-sitemap-plugin
https://github.com/smarek/Croogo-Sitemap-2.0
https://github.com/webtechnick/CakePHP-Seo-Plugin
Are these the old, error-causing ones? As each CakePHP site can be radically different to the next, I'm not sure a one-size-fits-all solution will exist.
If you end up writing your own sitemap implementation, it'll depend mainly on whether your site has:
Lots of database-driven content with few controllers/actions (like a typical WordPress-style site)
Lots of controller/action driven content (more of a web application)
In the first case, you'd want to perform finds on your content, and inject the results into an xml template like this: http://bakery.cakephp.org/articles/masterkeedu/2008/08/26/automatically-generate-dynamic-sitemaps
For the second case, the following may help: a component I've used for development/testing, which lists all controllers and their methods:
<?php //File: app/Controller/Component/CtrlComponent.php
// Component rewritten for Cake2.x, original from : http://cakebaker.42dh.com/2006/07/21/how-to-list-all-controllers/
class CtrlComponent extends Component {
/**
* Return an array of Controllers and their methods.
* The function will exclude ApplicationController methods
* #return array
*/
public function get() {
$aCtrlClasses = App::objects('controller');
foreach ($aCtrlClasses as $controller) {
if ($controller != 'AppController') {
// Load the controller
App::import('Controller', str_replace('Controller', '', $controller));
// Load its methods / actions
$aMethods = get_class_methods($controller);
foreach ($aMethods as $idx => $method) {
if ($method{0} == '_') {
unset($aMethods[$idx]);
}
}
// Load the ApplicationController (if there is one)
App::import('Controller', 'AppController');
$parentActions = get_class_methods('AppController');
$controllers[$controller] = array_diff($aMethods, $parentActions);
}
}
return $controllers;
}
}
In reality, a full sitemap probably uses both methods, and you'll need to consider the difference between public and "private" areas of your site (excluding admin prefixes, for example)..
Can't find any relevant information in the sencha documention about this question :
Is it possible to call Ext.create(...) with a parameter which does not depend on the application's name?
So that if I change the app's name I don't have to rewrite that line of code?
Normally I would use Ext.create(AppName.model.MYMODEL) but that's too tied to the app's name for me.
Still need help :)
Create using class alias
When using Ext.define to define your class, you can provide an alias property. You've probably seen this on UI components which use aliases like widget.panel. Those aliases can be used with Ext.create.
Ext.define('MyApp.SomeClass', {
alias: 'app.someclass', // Independent of class name
/* ... */
});
Ext.create('app.someclass', {
/* ... */
});
You can set the alias on a class after it has been created by using Ext.ClassManager.setAlias.
Helper function using application name
If you don't have the option to set an alias, you could create a function that wraps Ext.create which supplies your base namespace automatically.
The problem here is that Ext.application doesn't return the application object. I'm not sure how Sencha Architect generates the application code but you may need additional overrides to allow you to retrieve the application object.
function appCreate(className, config) {
var appName = someMethodThatGetsTheApplicationName();
return Ext.create(appName + '.' + className, config);
};
// Example usage: Creates object of MyApp.model.MyModel
var myObj = appCreate('model.MyModel', { /* ... */ });
How to get the application name at runtime
By default, Ext JS does not retain a reference to the application object when using Ext.application, so we need an override to do it. I'm using Ext.currentApp as the property to store this object, but you can change it to whatever you'd like.
Ext.application = function (config) {
Ext.require('Ext.app.Application');
Ext.onReady(function () {
Ext.currentApp = new Ext.app.Application(config);
});
};
Now that you have this, you can access the application name by simply using Ext.currentApp.name. Or, if you'd feel more comfortable using a getter you can use the following.
Ext.app.Application.addMembers({
getName: function () {
return this.name;
}
});
// Example usage:
function someMethodThatGetsTheApplicationName() {
if (!Ext.currentApp) {
Ext.Error.raise('Current app does not exist.');
}
return Ext.currentApp.getName();
}
You can use any class name in Ext.create there is no naming convention imposed there as long as the class was already defined. If you want Ext.create to load the correct file using Ext.loader you will need to configure the loader to conform with the naming convention you need.
The way to do it :
You need a controller that will in it's INIT function (before UI Loading/Initiating) do the following
APPNAME = this.getApplication().getName();
Where APPNAME is a global variable.
Then when you Ext.create something you will be able to write the following
Ext.create(APPNAME +'model.MyModel');
That way you can change you app name without having to check everywhere in your code to change every single Ext.create to the new app's name.
It also give you the ability if you are to use this.getApplication().setName() to have infinite cache storage has you get 5/10mb per AppName.
I use PhpStorm 6.0.2 and CakePHP 2.3.
In my controller file I define this and get autocomplete for my custom components:
/**
* #property MysuperComponent $Mysuper
*/
Regarding to this, in my view files I define this to reach Cake's core helpers and this works:
/**
* #var $this View
*/
I need autocomplete for custom helpers inside my views. I tried this but didn't work:
/**
* #property Myelegant $MyelegantHelper
*/
When I do this, this works partially:
/**
* #var $Myelegant MyelegantHelper
*/
I get this $Myelegant-> autocomplete. But it isn't adequate. I need autocomplete like this: $this->Myelegant->
Notes: Autocomplete successfully works for core helpers inside view (ctp) files. But not for custom helpers.
Add new file /app/View/HintView.php
Add your custom helpers' names on PHPDoc.
<?php
App::uses('View', 'View');
/**
* #property MyelegantHelper $Myelegant
* */
class HintView extends View {
}
Inside your layout files or View files (ctp files) add this code on top
/**
* #var $this HintView
*/
Now inside your views you can see like this:
$this->MyElegant
->Blocks
->Cache
->Form
$this->MyElegant->somefunction()
anotherfunction()
oldfunction()
You don't have to extend your Views from HintView. It is only for PhpStorm's autocomplete.
(Note that you can make it faster with creating shortcuts to codes. For example goto Settins / IDE Settings / Live Templates. Add new template. For example "myeleg" for "$this->MyElegant->" So when you write "myeleg" and press Tab key it will write the class name automatically)
Have you tried looking at this article:
http://blog.hwarf.com/2011/08/configure-phpstorm-to-auto-complete.html
Look at the section "Setting Up Helper Auto-completion in Views". Hopefully this helps.
I know this is an old post, but came across this having the same issue. Solved it this way:
For me, my custom helper is called StatusHelper, so needed the #property as follows:
App::uses('Helper', 'View');
/**
* #property StatusHelper $Status
* */
class StatusHelper extends AppHelper {
Then in the view .ctp file, I just needed the following at the top:
<?php /* #var $this View|StatusHelper */ ?>
Now the autocomplete works for my PHPstorm in that view for both core View vars as well as whatever ever methods are in my helper.. Happy days
Using Cake 2.5 - PHPstorm 10. Hope this helps someone else out there...
Is Easy, Test in CakePHP 3.x to PHPStrom, supports namespace.
Add in to file views.ctp type PHPDoc
<?php /** #var $this Cake\View\View */ ?>
I have a main page(controller_welcome => C_W), and another controllers; these extends from Controller_DefaultTemplatre(C_DT). In C_DT i have a function called addScripts() and addCss() these adds to url of the javascripts files and Css respectly to the View template, and getScripts() this last function get the array of the Scrips added by the current controller.
In C_W I have an action that calls anothers controllers via Request::factory("KONTROLLER/AKTION"); and puts all in the current template request.
/* content of the C_W */
$params = array();
$controller1_request = Request::factory("controller1/index");
$controller1_response = $controller1_request->execute();
$params["extra"] .= $controller1_response->body();
$controller2_request = Request::factory("controller2/index");
$controller2_response = $controller2_request->execute();
$params["extra"] .= $funny_response->body();
$this->template->content = View::factory("welcome/index", $params);
My question is: How I can add Scripts to the C_W Template from the Request::factory("controller1/index");?
Static vars?
For example, rewrite your addScripts() and addCss() to work with a static properties, so you can call it from any instance of C_DT. Of course, those methods must be static.
Or create special static class (helper) for it.