简体   繁体   English

Symfony 2 中 AngularJS 模板位置与新 Angular Router 的最佳实践?

[英]Best Practice with AngularJS template locations in Symfony 2 with the new Angular Router?

I am developing an AngularJS 1.4 Application within a Symfony2 Bundle.我正在 Symfony2 Bundle 中开发一个 AngularJS 1.4 应用程序。 Symfony provides the "backend" (API) and Angular the frontend (of course). Symfony 提供“后端”(API),Angular 提供前端(当然)。

I am using the new router and stick to the components driven folder approach suggested by several guides and best practice examples.我正在使用新的路由器并坚持使用多个指南和最佳实践示例建议的组件驱动文件夹方法。 But since I build my JavaScript with gulp and only include the complete Build-Files there are issues with Angular controllers not finding their templates.但是由于我使用 gulp 构建我的 JavaScript 并且只包含完整的构建文件,因此 Angular 控制器存在找不到模板的问题。

I show you my solution, which I don't like:我向您展示了我不喜欢的解决方案:

(function () {
'use strict';
angular
    .module('myModule', ['ngNewRouter', 'myModule.dashboard'])
    .config(TemplateMapping)
    .controller('AppController', AppController);

/* @ngInject */
function AppController ($router) {
    $router.config([
        { path: '/', redirectTo: '/dashboard' },
        { path: '/dashboard', component: 'dashboard' }
    ]);
}

/* @ngInject */
function TemplateMapping($componentLoaderProvider) {
    $componentLoaderProvider.setTemplateMapping(function (name) {
        return {
            'dashboard': '/bundles/mybundle/templates/dashboard/dashboard.html'
        }[name];
    });
}
}());

I write my Angular Code in src/myBundle/Resources/js/ and gulp puts the final Build to src/myBundle/Resources/public/ which is then available in the Twig Template that holds the Angular app.我在src/myBundle/Resources/js/编写我的 Angular 代码, src/myBundle/Resources/js/将最终的 Build 放到src/myBundle/Resources/public/ ,然后可以在包含 Angular 应用程序的 Twig 模板中使用它。

What I am doing right now, is basically putting the templates of my components not where they belong (that would be src/myBundle/Resources/js/components/dashboard/ for the dashboard example) but into src/myBundle/Resources/public/templates .我现在正在做的,基本上是将我的组件的模板放在它们所属的位置(对于仪表板示例,将是src/myBundle/Resources/js/components/dashboard/ ),而是放入src/myBundle/Resources/public/templates

I have to tell the router that the template is located elsewhere through $componentLoaderProvider.setTemplateMapping() .我必须通过$componentLoaderProvider.setTemplateMapping()告诉路由器模板位于其他地方。

I have two Questions:我有两个问题:

  1. Could I solve this template location problem in a more elegant way?我可以用更优雅的方式解决这个模板位置问题吗?
  2. Can I tell the router directly (in the AppController ) where the template is?我可以直接告诉路由器(在AppController )模板在哪里?

The cool thing with API based architectures is that you can uncouple the backend app (the API) from the frontend (the AngularJS app).基于 API 的架构很酷的一点是,您可以将后端应用程序(API)与前端(AngularJS 应用程序)分离。

I recommend to create two separate applications for frontend and backend.我建议为前端和后端创建两个单独的应用程序。 Each application should be in its own Git repository and can eventually be hosted on its own server:每个应用程序都应该在自己的 Git 存储库中,并且最终可以托管在自己的服务器上:

  • The Symfony application follows Symfony Best Practices and exposes only a REST API. Symfony 应用程序遵循Symfony 最佳实践并仅公开一个 REST API。 It holds all the business logic.它包含所有业务逻辑。 It has no template (you can remove Twig).它没有模板(您可以删除 Twig)。 Data will be preferably exposed in JSON.数据最好以 JSON 格式公开。
  • The AngularJS application relies on all frontend tools you want (Gulp, Yeoman...) and consumed the API. AngularJS 应用程序依赖于您想要的所有前端工具(Gulp、Yeoman...)并使用 API。 It manages the presentation and contains only "assets" (a static index.html file, JavaScript files, CSS stylesheets, images...).它管理演示文稿并且仅包含“资产”(静态index.html文件、JavaScript 文件、CSS 样式表、图像...)。

The API is the contract between the two side and they can evolve separately. API 是双方之间的契约,它们可以单独演进。 Maintenance is eased and the coupling is tight.维护容易,耦合紧密。 The frontend app can even be hosted directly on a CDN such as Amazon CloudFront or GitHub pages for maximum performance.前端应用程序甚至可以直接托管在 CDN 上,例如 Amazon CloudFront 或 GitHub 页面,以获得最佳性能。

I've written an article detailing this approach and presenting some tools I've built .我写了一篇文章详细介绍了这种方法并展示了我构建的一些工具 It uses Symfony and AngularJS.它使用 Symfony 和 AngularJS。

If you still want to have a single application:如果您仍然想要一个应用程序:

  • put the AngularJS app in a non-public directory such as app/frontend将 AngularJS 应用程序放在非公开目录中,例如app/frontend
  • configure the Gulp script to write dist files in web/配置 Gulp 脚本在web/写入 dist 文件
  • be careful to CSRF attacks (take a look at my DunglasAngularCsrfBundle )小心 CSRF 攻击(看看我的DunglasAngularCsrfBundle

The best approach as Kévin mentioned is to separate your front-end and back-end in a way that even if you change the back-end to another technology you don't need to change your front-end.正如 Kévin 提到的,最好的方法是将前端和后端分开,这样即使将后端更改为另一种技术,也不需要更改前端。

There are also 2 git projects that can help you to have a nicer app.还有 2 个 git 项目可以帮助您拥有更好的应用程序。

1) FOSJsRoutingBundle 1) FOSJsRoutingBundle

https://github.com/FriendsOfSymfony/FOSJsRoutingBundle Which allow you to use your Symfony routing in your JavaScript code https://github.com/FriendsOfSymfony/FOSJsRoutingBundle允许您在 JavaScript 代码中使用 Symfony 路由

2) angular-schema-form 2) angular-schema-form

https://github.com/json-schema-form/angular-schema-form Which is a dynamic form generator. https://github.com/json-schema-form/angular-schema-form这是一个动态表单生成器。 It creates and validates a form from a JSON schema.它从 JSON 模式创建并验证表单。

So what I did was to create a Angular Schema Form Serializer in Symfony to convert a Symfony form to a Jason schema which can be used by angular-schema-form to generate my forms dynamically.所以我所做的是在 Symfony 中创建一个 Angular Schema Form Serializer,将 Symfony 表单转换为 Jason 模式,angular-schema-form 可以使用它来动态生成我的表单。 In this case I don't need to implement form in html.在这种情况下,我不需要在 html 中实现表单。 Even if I change the API I just need to provide the same Jason schema for my forms.即使我更改了 API,我也只需要为我的表单提供相同的 Jason 模式。

The best approach is to separate completely your Angular app from Symfony backend.最好的方法是将 Angular 应用程序与 Symfony 后端完全分开。 But if you want to use the Angular in some very little part of your legacy app, you can pass your baseURL to your component, for ex.但是,如果您想在遗留应用程序的某个很小的部分中使用 Angular,您可以将 baseURL 传递给您的组件,例如。 :

<yourComponent baseurl="{{ app.request.scheme ~ '://' ~ 
app.request.httpHost ~ app.request.basePath }}"></yourComponent>

and then use it in your templateUrl function然后在你的 templateUrl 函数中使用它

    templateUrl: function($attrs) {
                return $attrs.baseurl + 'templats/yourComponent.template.html';
            }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM