标签:angular

以下是与标签 “angular” 相关联的文章

Angular 实用代码

左侧列表框

<mat-sidenav-container>
  <mat-sidenav #sidenav mode="side" opened="true" position="start">
    <mat-nav-list>
      <mat-list-item *ngFor="let product of productList;" (click)="onSelectProduct(product)">
        <mat-icon matListIcon>{{selectProduct == product ? 'label' : 'label_outline'}}</mat-icon>
        <span matLine>{{product}}</span>
      </mat-list-item>
    </mat-nav-list>
  </mat-sidenav>
  <div class="content">

SnackBar

onDeleteOrder(row: OrderItem) {
  let snackBarRef = this.snackBar.open("Are you sure to delete: " + row.id, "Delete", {
    duration: 3000
  });
  snackBarRef.onAction().subscribe(() => {
    this.regDataDao.deleteOrder(this.selectProduct, row.id).subscribe(data => {
      console.log(data);
      this.dataSource.data = this.dataSource.data.filter(
        orderItem => orderItem.id != row.id);
    });
  });
}

表格中可编辑元素

<mat-cell *matCellDef="let row">
  <div *ngIf="editOrderId == row.id; else else_part">
    <mat-form-field class="order-cell">
      <input matInput placeholder="{{row.order}}" [(ngModel)]="editOrder">
    </mat-form-field>
  </div>
  <ng-template #else_part>{{row.order}}</ng-template>
</mat-cell>

Angular 对话框使用

注入对话框引用

constructor(private dialogRef: MatDialogRef<AddOrderDialogComponent>) {
}

输入框校验

<mat-form-field>
  <input matInput type="email" placeholder="Email" tabindex="2" [ngModel]="email"
         (ngModelChange)="onEmailChange($event)" [formControl]="emailInput">
  <mat-error *ngIf="emailInput.hasError('email')">Error email format.</mat-error>
</mat-form-field>
emailInput = new FormControl();

onEmailChange(email: string) {
  this.email = email;
  if (this.emailAuth == true) {
    if (this.emailInput.hasError('email'))
      this.machine = '';
    else
      this.machine = this.getMachine(this.email);
  }
}

调用对话框

onAddOrder() {
  var dialogRef = this.addOrderDialog.open(AddOrderDialogComponent, {width: '300px'});
  dialogRef.componentInstance.product = this.selectProduct;
  dialogRef.afterClosed().subscribe(order => {
    this.regDataDao.addOrder(this.selectProduct, order).subscribe(data => {
      console.log(data);
      this.dataSource.data.push(data);
      this.dataSource.data = this.dataSource.data;
    });
  });
}

关闭对话框

onAddOrder() {
  var result = {name: this.name, email: this.email, machine: this.machine};
  // console.log(result);
  this.dialogRef.close(result);
}

Spring Boot + Spring Security + Angular 配置

最简单配置

  • 弹出登录对话框
  • 自定义用户名密码
@Configurable
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity httpSecurity) {
        try {
            httpSecurity.authorizeRequests().anyRequest().authenticated()
                    .and()
                    .httpBasic();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Autowired
    public void ConfigureGlobal(AuthenticationManagerBuilder auth) {
        try {
            auth.inMemoryAuthentication().withUser("root").password("123456").roles("ADMIN");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

自定义 LoginForm

  • 自定义 form 提交地址
  • 认证结果不跳转
  • 登录对话框中,允许资源访问
@Configurable
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomAuthFailureHandler customAuthFailureHandler;

    @Autowired
    private CustomLoginSuccessHandler customLoginSuccessHandler;

    @Autowired
    private CustomLogoutSuccessHandler customLogoutSuccessHandler;

    Gson gson = new Gson();

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                    .anyRequest().authenticated()
                    .and()
                .formLogin()
                    .loginPage("/login").loginProcessingUrl("/auth")
                    .successHandler(customLoginSuccessHandler)
                    .failureHandler(customAuthFailureHandler)
                    .and()
                .logout().permitAll().logoutSuccessUrl("/logout")
                    .logoutSuccessHandler(customLogoutSuccessHandler)
        ;
        http.csrf().disable();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().regexMatchers(".*\\.js", ".*\\.css", ".*\\.ico", ".*\\.woff2");
    }

    @Autowired
    public void ConfigureGlobal(AuthenticationManagerBuilder auth) {
        try {
            auth.inMemoryAuthentication()
                    .withUser("root").password("123456").roles("ADMIN");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected class NoRedirectStrategy implements RedirectStrategy {
        @Override
        public void sendRedirect(HttpServletRequest request,
                                 HttpServletResponse response, String url) throws IOException {
            // no redirect
        }
    }

    @Component
    public class CustomLoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

        public CustomLoginSuccessHandler() {
            super();
            setRedirectStrategy(new NoRedirectStrategy());
        }

        @Override
        public void onAuthenticationSuccess(HttpServletRequest request,
                                            HttpServletResponse response,
                                            Authentication authentication)
                throws ServletException, IOException {
            super.onAuthenticationSuccess(request, response, authentication);
            Writer writer = response.getWriter();
            writer.write(gson.toJson("success"));
        }
    }

    @Component
    public class CustomAuthFailureHandler extends SimpleUrlAuthenticationFailureHandler {

        public CustomAuthFailureHandler() {
            super();
            setRedirectStrategy(new NoRedirectStrategy());
        }

        @Override
        public void onAuthenticationFailure(HttpServletRequest request,
                                            HttpServletResponse response,
                                            AuthenticationException exception)
                throws IOException, ServletException {
            String error = exception.getMessage();
            //getRedirectStrategy().sendRedirect(request, response, "/login?error=" + error);
            Writer writer = response.getWriter();
            writer.write(gson.toJson(error));
        }
    }

    @Component
    public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
        @Override
        public void onLogoutSuccess(HttpServletRequest request,
                                    HttpServletResponse response,
                                    Authentication authentication)
                throws IOException, ServletException {
            Writer writer = response.getWriter();
            writer.write(gson.toJson("success"));
        }
    }
}

Angular 提交

  • 登录
onLogin() {
    const url = '/auth';
    // let data = {username: this.username, password: this.password };
    // let data = "username=" + this.username + "&password=" + this.password;
    let params = new URLSearchParams();
    params.set('username', this.username);
    params.set('password', this.password);

    let header = {
      headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded'),
    };

    this.http.post(url, params.toString(), header).subscribe(
      data => {
        console.log(data);
        if (data != null && data == 'success') {
          this.router.navigateByUrl("/");
        } else {
          let snackBarRef = this.snackBar.open("Login failed. " + data, "CLOSE", {
            duration: 3000
          });
          snackBarRef.onAction().subscribe();
        }
      },
      err => {
        console.log("error: " + err.errorMsg);
      }
    );
  }
  • 登出
logout() {
  this.http.get('/logout').subscribe( data => {
    this.router.navigateByUrl('/login');
  });
}

angular2 学习笔记(2)- 添加 material 组件

添加组件

  • 命令行

    npm install --save @angular/material material-design-icons @angular/animations @angular/flex-layout hammerjs
    
    

添加配置

  • app.module.ts

    imports: [    
      ...
      BrowserAnimationsModule,
      MdToolbarModule, MdButtonModule, MdMenuModule, MdIconModule,
      FlexLayoutModule,
    ],
    
  • style.css

    @import '~@angular/material/core/theming/prebuilt/deeppurple-amber.css';
    
    /* fallback */
    @font-face {
      font-family: 'Material Icons';
      font-style: normal;
      font-weight: 400;
      src: url(../node_modules/material-design-icons/iconfont/MaterialIcons-Regular.woff2) format('woff2');
    }
    
    .material-icons {
      font-family: 'Material Icons';
      font-weight: normal;
      font-style: normal;
      font-size: 24px;
      line-height: 1;
      letter-spacing: normal;
      text-transform: none;
      display: inline-block;
      white-space: nowrap;
      word-wrap: normal;
      direction: ltr;
      -webkit-font-feature-settings: 'liga';
      -webkit-font-smoothing: antialiased;
    }
    

测试页面

  • html demo

    <md-toolbar color="primary">
      <button md-icon-button [mdMenuTriggerFor]="menu1">
        <md-icon>more_vert</md-icon>
      </button>
      <md-menu #menu1="mdMenu">
        <button md-menu-item>
          <md-icon>fingerprint</md-icon>
          <span>Login</span>
        </button>
        <button md-menu-item disabled>
          <md-icon>annoucement</md-icon>
          <span>Issues</span>
        </button>
        <button md-menu-item>
          <md-icon>notifications_off</md-icon>
          <span>No Alerts</span>
        </button>
      </md-menu>
      <span>fj's blog</span>
    </md-toolbar>
    

angular2 学习笔记(1)- 工具配置和框架搭建

搭建 springboot 工程

工程框架

  • File -> New -> Project -> Spring Initializer
  • Dependencies: Web->Web, Template Engine->Thymeleaf
  • Thymeleaf 修改为 LEGACY 模式
    • pom.xml 中添加依赖

      <dependency>
        <groupId>net.sourceforge.nekohtml</groupId>
        <artifactId>nekohtml</artifactId>
      </dependency>
      
    • 修改 application.properties

      spring.thymeleaf.mode=LEGACYHTML5
      spring.thymeleaf.cache=false
      

Bean 配置

  • 添加类 BeanConfig

    @Configuration
    @ImportResource("classpath:bean.xml")
        public class BeanConfig {
    }
    
  • 在 src->main->resources 下添加文件 bean.xml,并添加 Bean 实例

    <bean name="myBean" class="com.fj.springboot01.MyBean"/>
    

添加路由

  • 给类添加注解 @Controller
  • 给类添加方法

    @RequestMapping("/hello")
    public String hello() {
      System.out.println("hello mapping");
      return "hello";
    }
    
  • 添加 hello.html ,放在 src/main/resources/templates 目录下

添加静态资源

  • angular2 生成的页面作为静态资源放在 src/main/resources/static 目录下

搭建 angular2 框架

安装软件

  • 下载并安装 node.js LTS 版本到 D:/nodejs 目录
  • 安装 cnpm

    npm install -g cnpm --registry=https://registry.npm.taobao.org
    
    
  • 修改 C:/Users/fj/.npmrc

    registry=https://registry.npm.taobao.org/
    prefix=D:\nodejs
    cache=D:\nodejs\node_cache
    
  • 安装 npm 软件包

    npm install -g @angular/cli webpack typescript tslint
    
    

工程框架

  • 新建代码框架,下载依赖

    cd spring001/src/main
    ng new angular
    cd angular
    npm install
    
  • 新建 Component

    ng g c component/data-grid
    
    
  • 修改页面

编译

  • 命令行编译生成目标文件

    ng build --prod --aot --bh /note/ --no-extract-license
    
    
  • 修改 package.json , 添加两行

    "scripts": {
      "develop":"ng build -bh /note/ -w",
      "release":"ng build -bh /note/ -prod -aot --env=prod --no-extract-license"
    },
    
  • 将目标文件移动到静态资源目录下, 修改 .angular-cli.json

    "outDir": "../resources/static/note", 
    

调试

  • tsconfig.json 中打开 sourceMap 选项

    "sourceMap": true,
    "inlineSources": true,
    
  • 在 IDEA 中直接创建 SpringBoot 启动项
  • 启动调试