Coder Social home page Coder Social logo

cipchk / ngx-ueditor Goto Github PK

View Code? Open in Web Editor NEW
173.0 14.0 48.0 5.42 MB

Angular for Baidu UEditor

Home Page: https://cipchk.github.io/ngx-ueditor/

License: MIT License

JavaScript 86.39% TypeScript 1.25% HTML 5.25% CSS 5.95% C# 0.99% ASP.NET 0.17%
ueditor baidu-ueditor angular angular-component angular-components ng-alain ngx-ueditor

ngx-ueditor's Introduction

当前 UEditor 已经不再维护的情况下,为了不误导大家,从 Angular 14 开始将不再维护。可以尝试使用 ngx-tinymce 来代替。

ngx-ueditor

Angular2.x for Baidu UEditor(UMeditor

NPM version Ci

Demo

特性

  • 懒加载 ueditor.all.js 文件。
  • 支持ueditor事件监听与移除
  • 支持语言切换
  • 支持ueditor实例对象直接访问。
  • 支持二次开发。

使用

1、安装

npm install ngx-ueditor --save

UEditorModule 模块导入到你项目中。

import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { UEditorModule } from 'ngx-ueditor';

@NgModule({
  imports: [ 
    BrowserModule,
    FormsModule,
    UEditorModule.forRoot({
      js: [
        `./assets/ueditor/ueditor.config.js`,
        `./assets/ueditor/ueditor.all.min.js`,
      ],
      // 默认前端配置项
      options: {
        UEDITOR_HOME_URL: './assets/ueditor/'
      }
    })
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }

2、使用

<ueditor [(ngModel)]="html" 
         [config]="{ wordCount: true }"
         [loadingTip]="'加载中……'"
         (onReady)="_ready($event)"
         (onDestroy)="_destroy()"
         (ngModelChange)="_change($event)"></ueditor>
名称 类型 默认值 描述
config Object - 前端配置项说明,见官网
loadingTip string 加载中... 初始化提示文本
disabled boolean false 是否禁用
delay number 50 延迟初始化UEditor,单位:毫秒
onPreReady EventEmitter<UEditorComponent> - 编辑器准备就绪之前会触发该事件,并会传递 UEditorComponent 当前实例对象,可用于后续操作(比如:二次开发前的准备)。
onReady EventEmitter<UEditorComponent> - 编辑器准备就绪后会触发该事件,并会传递 UEditorComponent 当前实例对象,可用于后续操作。
onDestroy EventEmitter - 编辑器组件销毁后会触发该事件
ngModelChange EventEmitter<string> - 编辑器内容发生改变时会触发该事件

3、关于懒加载

懒加载在未到 wdinow.UE 时会启动,如果你在 index.html 已经使用 <script src="ueditor.all.js"></script> 加载过,懒加载流程将会失效。

加载语言注意点

懒加载会自动识别并引用,否则,需要自行在 <head> 加入语言版本脚本。

访问ueditor实例对象

首先,需要给组件定义一下模板变量:

<ueditor [(ngModel)]="full_source" #full></ueditor>

使用 @ViewChild 访问组件,并使用 this.full.Instance 访问ueditor实例对象。

export class DemoComponent {
  @ViewChild('full') full: UEditorComponent;
  constructor(private el: ElementRef) {}

  getAllHtml() {
    // 通过 `this.full.Instance` 访问ueditor实例对象
    alert(this.full.Instance.getAllHtml())
  }
}

事件

虽说上节也可以直接注册ueditor事件,但当组件被销毁时可能会引发内存泄露。所以不建议直接在ueditor实例中这么做。组件本身提供 addListenerremoveListener 来帮你处理。

// 事件监听
this.full.addListener('focus', () => {
  this.focus = `fire focus in ${new Date().getTime()}`;
});
// 事件移除
this.full.removeListener('focus');

二次开发

onPreReady

onPreReady 是指在UEditor创建前会触发;因此,可以利用这个事件做一些针对二次开发的准备工作。比如,针对本实例创建自定义一个按钮:

<ueditor [(ngModel)]="custom_source" (onPreReady)="onPreReady($event)" [config]="custom"></ueditor>
onPreReady(comp: UEditorComponent) {
  UE.registerUI('button', function(editor, uiName) {
    //注册按钮执行时的command命令,使用命令默认就会带有回退操作
    editor.registerCommand(uiName, {
      execCommand: function() {
        alert('execCommand:' + uiName)
      }
    });
    //创建一个button
    var btn = new UE.ui.Button({
      //按钮的名字
      name: uiName,
      //提示
      title: uiName,
      //添加额外样式,指定icon图标,这里默认使用一个重复的icon
      cssRules: 'background-position: -500px 0;',
      //点击时执行的命令
      onclick: function() {
        //这里可以不用执行命令,做你自己的操作也可
        editor.execCommand(uiName);
      }
    });
    //当点到编辑内容上时,按钮要做的状态反射
    editor.addListener('selectionchange', function() {
      var state = editor.queryCommandState(uiName);
      if (state == -1) {
        btn.setDisabled(true);
        btn.setChecked(false);
      } else {
        btn.setDisabled(false);
        btn.setChecked(state);
      }
    });
    //因为你是添加button,所以需要返回这个button
    return btn;
  }, 5, comp.id);
  // comp.id 是指当前UEditor实例Id
}

Hook

hook调用会在UE加载完成后,UEditor初始化前调用,而且这个整个APP中只会调用一次,通过这个勾子可以做全局性的二次开发。

UEditorModule.forRoot({
    js: [
      `./assets/ueditor/ueditor.config.js`,
      `./assets/ueditor/ueditor.all.min.js`,
    ],
    // 默认前端配置项
    options: {
      UEDITOR_HOME_URL: './assets/ueditor/'
    },
    hook: (UE: any): void => {
      // button 自定义按钮将在所有实例中有效。
      UE.registerUI('button', function(editor, uiName) {
        //注册按钮执行时的command命令,使用命令默认就会带有回退操作
        editor.registerCommand(uiName, {
          execCommand: function() {
            alert('execCommand:' + uiName)
          }
        });
        //创建一个button
        var btn = new UE.ui.Button({
          //按钮的名字
          name: uiName,
          //提示
          title: uiName,
          //添加额外样式,指定icon图标,这里默认使用一个重复的icon
          cssRules: 'background-position: -500px 0;',
          //点击时执行的命令
          onclick: function() {
            //这里可以不用执行命令,做你自己的操作也可
            editor.execCommand(uiName);
          }
        });
        //当点到编辑内容上时,按钮要做的状态反射
        editor.addListener('selectionchange', function() {
          var state = editor.queryCommandState(uiName);
          if (state == -1) {
            btn.setDisabled(true);
            btn.setChecked(false);
          } else {
            btn.setDisabled(false);
            btn.setChecked(state);
          }
        });
        //因为你是添加button,所以需要返回这个button
        return btn;
      });
    }
})

表单非空校验

组件加入 required 当编辑器为空时会处于 ng-invalid 状态,具体体验见Live Demo

常见问题

Cannot read property 'getDom' of undefined

当你快速切换路由时,可能会引起:Cannot read property 'getDom' of undefined 异常,这是因为 UEditor 在初始化过程中是异步行为,当 Angular 组件被销毁后其 DOM 也一并被移除,这可能导致进行初始化中的 UEditor 无法找到相应 DOM。我们无法避免这种错误,可以使用 delay 延迟启动初始化 Ueditor 适当地减少这种快速切换路由的问题。

关于图片上传

UEditor 自带单图、多图上传,只需要配置 options.serverUrl 服务端路径即可,有关更多上传细节 百度:Ueditor

若自身已经系统包含类似_淘宝图片_统一图片管理可以自行通过二次开发图片资源选取按钮。

Troubleshooting

Please follow this guidelines when reporting bugs and feature requests:

  1. Use GitHub Issues board to report bugs and feature requests (not our email address)
  2. Please always write steps to reproduce the error. That way we can focus on fixing the bug, not scratching our heads trying to reproduce it.

Thanks for understanding!

License

The MIT License (see the LICENSE file for the full text)

ngx-ueditor's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ngx-ueditor's Issues

怎么调用打印方法

内容是只读状态,所以ueditor的默认打印按钮也是不能点击的。这种情况我要怎么才能实现打印呢?

本地调试这个组件时,弹出对话框默认样式无效

ueditor-bug-snapshort
我首先在自己的项目中添加UEditorModule并在模板上应用,编辑器的功能是完好的,但是弹出对话框的样式都消失了,如标签页span元素的背景渐变和边框等等。
后来我克隆了完整的ngx-ueditor仓库,npm ing serve,demo组件在浏览器中的效果依然有bug。
然而在GitHub Pages上面的demo显然是完好的。
ueditor-origin-snapshort
我个人猜测这个问题在于路径,于是显示地配置了theme和themePath为默认配置(我没有写自己的css),但是这个bug依然存在。
目前我没有其他的思路来解决这个问题,也不太清楚这个bug的根本原因是在于我的使用方式还是module本身,希望作者(或者任何能帮助我的人)能给我一点提示([email protected], 或者直接回复issue)。

关于跨域上传的改进

`package ueditorgobackend

import (
// "github.com/astaxie/beego" 1. uncomment this if you want to use it with beego
"encoding/json"
"fmt"
"io"
"io/ioutil"
"math/rand"
"mime/multipart"
"net/http"
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
)

type UEditorConfig map[string]interface{}
type UploadConfig struct {
pathFormat string
maxSize int64
allowFiles []string
origName string
}

var ueditorConfig UEditorConfig
var serverPath string
var configJsonPath = "../ueditor/go/config.json"

var stateMap = map[string]string{
"0": "SUCCESS",
"1": "文件大小超出 upload_max_filesize 限制",
"2": "文件大小超出 MAX_FILE_SIZE 限制",
"3": "文件未被完整上传",
"4": "没有文件被上传",
"5": "上传文件为空",
"ERROR_TMP_FILE": "临时文件错误",
"ERROR_TMP_FILE_NOT_FOUND": "找不到临时文件",
"ERROR_SIZE_EXCEED": "文件大小超出网站限制",
"ERROR_TYPE_NOT_ALLOWED": "文件类型不允许",
"ERROR_CREATE_DIR": "目录创建失败",
"ERROR_DIR_NOT_WRITEABLE": "目录没有写权限",
"ERROR_FILE_MOVE": "文件保存时出错",
"ERROR_FILE_NOT_FOUND": "找不到上传文件",
"ERROR_WRITE_CONTENT": "写入文件内容错误",
"ERROR_UNKNOWN": "未知错误",
"ERROR_DEAD_LINK": "链接不可用",
"ERROR_HTTP_LINK": "链接不是http链接",
"ERROR_HTTP_CONTENTTYPE": "链接contentType不正确",
}

type Size interface {
Size() int64
}

type Stat interface {
Stat() (os.FileInfo, error)
}

func init() {
serverPath = getCurrentPath()
ueditorConfig = make(UEditorConfig)
readConfig(configJsonPath)
}

/** 2. uncomment this if you want to use it with beego
type UEditorController struct{
beego.Controller
}
**/

type Uploader struct {
request *http.Request
fileField string
file multipart.File
base64 string
config UEditorConfig
oriName string
fileName string
fullName string
filePath string
fileSize int64
fileType string
stateInfo string
optype string
}

func HandleUpload(w http.ResponseWriter, r *http.Request) {
var fieldName string = "upload"
var config UEditorConfig
var fbase64 string
var result map[string]string
var responseBytes []byte

//跨域上传,会首先发起OPTIONS请求,然后才是真实请求,这里进行处理
if r.Method == "OPTIONS" {
	if origin := r.Header.Get("Origin"); origin != "" {
		w.Header().Set("Access-Control-Allow-Origin", origin)
		w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
		w.Header().Set("Access-Control-Allow-Headers",
			"X_Requested_With,Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
	}
	return
}
//真实请求从这里开始,若跨域,header仍需设置
if origin := r.Header.Get("Origin"); origin != "" {
	w.Header().Set("Access-Control-Allow-Origin", origin)
	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
	w.Header().Set("Access-Control-Allow-Headers",
		"X_Requested_With,Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}
r.ParseMultipartForm(32 << 20) // TODO: read it from config

//前端跨域请求会有callback字段,这里构造返回请求格式
//同域正常返回,否则把返回值包到回调函数里作为语句返回
//注意,任何回写response需要前缀语句:
//resopnseTemplate[2]=string(responseBytes[:])
//responseBytes=[]byte(strings.Join(resopnseTemplate,""))
callBack, ok := r.Form["callback"]
resopnseTemplate := []string{"FuncPlaceHolder", "(", "jsonPlaceHolder", ");"}
if ok {
	w.Header().Set("Content-Type", "application/javascript")
	//fmt.Println(callBack[0])
	resopnseTemplate[0] = callBack[0]
} else {
	resopnseTemplate[0] = ""
	resopnseTemplate[1] = ""
	resopnseTemplate[3] = ""
	w.Header().Set("Content-Type", "application/json;charset=utf8")
}

action := r.Form["action"]
switch action[0] {
case "config":
	responseBytes, _ = json.Marshal(&ueditorConfig)
	resopnseTemplate[2] = string(responseBytes[:])
	responseBytes = []byte(strings.Join(resopnseTemplate, ""))
	w.Write(responseBytes)
	return
case "uploadimage":
	config = UEditorConfig{
		"pathFormat": ueditorConfig["imagePathFormat"],
		"maxSize":    ueditorConfig["imageMaxSize"],
		"allowFiles": ueditorConfig["imageAllowFiles"],
	}
	fieldName = ueditorConfig["imageFieldName"].(string)

case "uploadscrawl":
	config = UEditorConfig{
		"pathFormat": ueditorConfig["scrawPathFormat"],
		"maxSize":    ueditorConfig["scrawMaxSize"],
		"allowFiles": ueditorConfig["scrawlAllowFiles"],
		"oriname":    "scrawl.png",
	}
	fieldName = ueditorConfig["scrawFieldName"].(string)
	fbase64 = "base64"
case "uploadvideo":
	config = UEditorConfig{
		"pathFormat": ueditorConfig["videoPathFormat"],
		"maxSize":    ueditorConfig["videoMaxSize"],
		"allowFiles": ueditorConfig["videoAllowFiles"],
	}
	fieldName = ueditorConfig["videoFieldName"].(string)
case "uploadfile":
	config = UEditorConfig{
		"pathFormat": ueditorConfig["filePathFormat"],
		"maxSize":    ueditorConfig["fileMaxSize"],
		"allowFiles": ueditorConfig["fileAllowFiles"],
	}
	fieldName = ueditorConfig["fileFieldName"].(string)
default:
	responseBytes, _ = json.Marshal(map[string]string{
		"state": "请求地址出错",
	})
	resopnseTemplate[2] = string(responseBytes[:])
	responseBytes = []byte(strings.Join(resopnseTemplate, ""))
	//fmt.Println("respenseBytes:", responseBytes)
	w.Write(responseBytes)
	return
}
config["maxSize"] = int64(config["maxSize"].(float64))
uploader := NewUploader(r, fieldName, config, fbase64)

uploader.upFile()
result = uploader.getFileInfo()
responseBytes, _ = json.Marshal(result)

resopnseTemplate[2] = string(responseBytes[:])
responseBytes = []byte(strings.Join(resopnseTemplate, ""))
w.Write(responseBytes)

}

/** 3. uncomment this if you want to use it with beego
func (this *UEditorController) Handle() {
var fieldName string = "upload"
var config UEditorConfig
var fbase64 string
var result map[string]string

action := this.GetString("action")
switch (action) {
case "config":
	this.Data["json"] = &ueditorConfig
	this.ServeJSON()
	return
case "uploadimage":
	config = UEditorConfig{
		"pathFormat" : ueditorConfig["imagePathFormat"],
		"maxSize" : ueditorConfig["imageMaxSize"],
		"allowFiles" : ueditorConfig["imageAllowFiles"],
	}
	fieldName = ueditorConfig["imageFieldName"].(string)
case "uploadscrawl":
	config = UEditorConfig{
		"pathFormat" : ueditorConfig["scrawPathFormat"],
		"maxSize" : ueditorConfig["scrawMaxSize"],
		"allowFiles" : ueditorConfig["scrawlAllowFiles"],
		"oriname" : "scrawl.png",
	}
	fieldName = ueditorConfig["scrawFieldName"].(string)
	fbase64 = "base64"
case "uploadvideo":
	config = UEditorConfig{
		"pathFormat" : ueditorConfig["videoPathFormat"],
		"maxSize": ueditorConfig["videoMaxSize"],
		"allowFiles" : ueditorConfig["videoAllowFiles"],
	}
	fieldName = ueditorConfig["videoFieldName"].(string)
case "uploadfile":
	config = UEditorConfig{
		"pathFormat" : ueditorConfig["filePathFormat"],
		"maxSize" : ueditorConfig["fileMaxSize"],
		"allowFiles" : ueditorConfig["fileAllowFiles"],
	}
	fieldName = ueditorConfig["fileFieldName"].(string)
default:
	this.Data["json"] = &map[string]string{
		"state" : "请求地址出错",
	}
	this.ServeJSON()
	return
}
config["maxSize"] = int64(config["maxSize"].(float64))
uploader := NewUploader(this.Ctx.Request, fieldName, config, fbase64)

uploader.upFile()
result = uploader.getFileInfo()

this.Data["json"] = &result
this.ServeJSON()

}
**/

func NewUploader(request *http.Request, fileField string, config UEditorConfig, optype string) (uploader *Uploader) {
uploader = new(Uploader)
uploader.request = request
uploader.fileField = fileField
uploader.config = config
uploader.optype = optype

return

}

func (this *Uploader) upFile() {

this.request.ParseMultipartForm(this.config["maxSize"].(int64))
file, fheader, err := this.request.FormFile(this.fileField)
defer file.Close()
if err != nil {
	this.stateInfo = err.Error()
	fmt.Printf("upload file error: %s", err)
} else {
	this.oriName = fheader.Filename
	if stateInterface, ok := file.(Stat); ok {
		fileInfo, _ := stateInterface.Stat()
		this.fileSize = fileInfo.Size()
	} else {
		this.stateInfo = this.getStateInfo("ERROR_UNKNOWN")
	}

	this.fileType = this.getFileExt()
	this.fullName = this.getFullName()
	this.filePath = this.getFilePath()
	this.fileName = this.getFileName()

	dirname := path.Dir(this.filePath)

	if !this.checkSize() {
		this.stateInfo = this.getStateInfo("ERROR_SIZE_EXCEED")
		return
	}

	if !this.checkType() {
		this.stateInfo = this.getStateInfo("ERROR_TYPE_NOT_ALLOWED")
		return
	}

	dirInfo, err := os.Stat(dirname)
	if err != nil {
		err = os.MkdirAll(dirname, 0666)
		if err != nil {
			this.stateInfo = this.getStateInfo("ERROR_CREATE_DIR")
			fmt.Printf("Error create dir: %s", err)
			return
		}
	} else if dirInfo.Mode()&0222 == 0 {
		this.stateInfo = this.getStateInfo("ERROR_DIR_NOT_WRITEABLE")
		return
	}

	fout, err := os.OpenFile(this.filePath, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		this.stateInfo = this.getStateInfo("ERROR_FILE_MOVE")
		return
	}
	defer fout.Close()

	io.Copy(fout, file)
	// if err != nil {
	// 	this.stateInfo = this.getStateInfo("ERROR_FILE_MOVE");
	// 	return
	// }

	this.stateInfo = stateMap["0"]
}

}

func (this *Uploader) getStateInfo(errCode string) string {
if errInfo, ok := stateMap[errCode]; ok {
return errInfo
} else {
return stateMap["ERROR_UNKNOWN"]
}
}

func (this *Uploader) getFileExt() string {
pos := strings.LastIndex(this.oriName, ".")
return strings.ToLower(this.oriName[pos:])
}

func (this *Uploader) getFullName() string {
t := time.Now()
format := this.config["pathFormat"].(string)

format = strings.Replace(format, "{yyyy}", strconv.Itoa(t.Year()), 1)

format = strings.Replace(format, "{mm}", strconv.Itoa(int(t.Month())), 1)
format = strings.Replace(format, "{dd}", strconv.Itoa(t.Day()), 1)
format = strings.Replace(format, "{hh}", strconv.Itoa(t.Hour()), 1)
format = strings.Replace(format, "{ii}", strconv.Itoa(t.Minute()), 1)
format = strings.Replace(format, "{ss}", strconv.Itoa(t.Second()), 1)
format = strings.Replace(format, "{time}", strconv.FormatInt(t.Unix(), 10), 1)

reg := regexp.MustCompile("{rand:[0-9]+}")
randstrs := reg.FindAllString(format, -1)

randNum := ""
if len(randstrs) != 0 {
	//只考虑第一个{rand:n}
	reg = regexp.MustCompile("[0-9]+")
	digitNumber, err := strconv.Atoi(reg.FindAllString(randstrs[0], -1)[0])
	if err == nil {
		for i := 1; i <= digitNumber; i++ {
			randNum += strconv.Itoa(rand.Intn(10))
		}

		format = strings.Replace(format, randstrs[0], randNum, 1)
	}
}
//format = format + randNum

return format + this.getFileExt()

}

func (this *Uploader) getFileName() string {
pos := strings.LastIndex(this.filePath, "/")
return this.filePath[pos+1:]
}

func (this *Uploader) getFilePath() string {
fullname := this.fullName

if strings.LastIndex(fullname, "/") == (len(fullname) - 1) {
	fullname = "/" + fullname
}

return serverPath + fullname

}

func (this *Uploader) checkType() bool {
found := false
for _, ext := range this.config["allowFiles"].([]interface{}) {
if ext.(string) == this.fileType {
found = true
break
}
}

return found

}

func (this *Uploader) checkSize() bool {
return this.fileSize <= (this.config["maxSize"].(int64))
}

func (this *Uploader) getFileInfo() map[string]string {
return map[string]string{
"state": this.stateInfo,
"url": this.fullName,
"title": this.fileName,
"original": this.oriName,
"type": this.fileType,
"size": string(this.fileSize),
}
}

func readConfig(configPath string) {
fd, err := os.Open(serverPath + "/" + configPath)
checkError(err)
defer fd.Close()

data, err := ioutil.ReadAll(fd)
checkError(err)

pattern := regexp.MustCompile(`/\*.+?\*/`)
data = pattern.ReplaceAll(data, []byte(""))

json.Unmarshal(data, &ueditorConfig)
//fmt.Println(string(data))

}

func getCurrentPath() string {
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
checkError(err)

return strings.Replace(dir, "\\", "/", -1)

}

func checkError(err error) {
if err != nil {
fmt.Printf("Error: %s", err)
}
}
`

使用ngx-ueditor前端上传图片如何配置

我现在页面中引入了ngx-ueditor;之前的上传图片是通过js调用接口来上传的,ngx-ueditor改如何配置?
使用umeditor时,我是这样配置的
this.editor = UE.getEditor('newsEditor',{
uploadProc: this.uploadProc.bind(this),
imageFieldName: "file",
imagePath: "",
//图片修正地址,引用了fixedImagePath,如有特殊需求,可自行配置
//工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的从新定义
toolbar: [
'source | bold italic underline strikethrough | superscript subscript | forecolor backcolor | removeformat |',
'insertorderedlist insertunorderedlist | fontsize',
'| justifyleft justifycenter justifyright justifyjustify ',
'| image video fullscreen '
]
});

uploadProc是我在写的一个上传图片的方法

配置问题

你好,我完成 UEditorModule 模块导入到项目后,在模版文件中加入
<ueditor [(ngModel)]="full_source"
[config]="{...}"
[loadingTip]="'加载中……'"
(onReady)=""
(onDestroy)=""
(onContentChange)="">

然后浏览器显示解析错误:
Parser Error: Unexpected token ., expected identifier, keyword, or string at column 2 in [{...}] in ng:///AppModule/AppComponent.html@1:9 ("<ueditor [(ngModel)]="full_source"
[ERROR ->][config]="{...}"
[loadingTip]="'加载中……'"
(onReady)=""
"): ng:///AppModule/AppComponent.html@1:9

请问我是什么地方配置错了,感谢

Ueditor 页面可以显示,但是会报错 If ngModel is used within a form tag

加上 [(ngModel)]会报错
<ueditor [(ngModel)]="full_source" [config]="config">

If ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as 'standalone' in ngModelOptions.

去掉 ngModel 就不会报错
<ueditor [config]="config">

环境:
Angular 5.0.0
ueditor 1.4.3.3
ngx-ueditor1.1.0

部署路径问题

你好,因为这边项目部署时需要用到nginx服务器,然后会指定目录,比如test。
因此项目编译时我用了deploy-url=test这个参数,但是ngx-ueditor forRoot时传入的参数没法一起改掉,导致部署后无法加载ueditor。
请问是否有好的解决方案?万分感谢。

当编辑器中有内容的时候销毁组件会报错

报错信息如下:
Uncaught TypeError: Cannot read property 'lang' of undefined
at UE.Editor.getLang (ueditor.all.js:7893)
at ueditor.all.js:29557
at ZoneDelegate.webpackJsonp.802.ZoneDelegate.invokeTask (zone.js:424)
at Zone.webpackJsonp.802.Zone.runTask (zone.js:191)
at ZoneTask.invoke (zone.js:486)
at timer (zone.js:1512)
如果再销毁组件之前先清空内容,报另外的错,报错信息如下:
ERROR TypeError: Cannot read property 'nodeType' of undefined
at Object.isEmptyBlock (ueditor.all.js:3938)
at UE.Editor.hasContents (ueditor.all.js:7690)
at save (ueditor.all.js:23928)
at ueditor.all.js:23990
at ZoneDelegate.webpackJsonp.802.ZoneDelegate.invokeTask (zone.js:424)
at Object.onInvokeTask (core.es5.js:4140)
at ZoneDelegate.webpackJsonp.802.ZoneDelegate.invokeTask (zone.js:423)
at Zone.webpackJsonp.802.Zone.runTask (zone.js:191)
at ZoneTask.invoke (zone.js:486)
at timer (zone.js:1512)

如果不填充任何内容或者手动切换了源代码视图以后销毁组件就不会报错

angular4引入后报metadata 版本不对

ERROR in Metadata version mismatch for module H:/workspace/ui-dzxt-project/node_modules/ngx-ueditor/index.d.ts, found version 4, expected 3,
引入后报这个错~用的ng4 求指点啊~~

_this.onChange is not a function

ueditor.addListener('contentChange', function () {
_this.value = ueditor.getContent();
_this.zone.run(function () { return _this.onChange(_this.value); });
});

将angular2.X升级到4.X以后报错

报错内容:ERROR TypeError: Cannot read property 'Instance' of undefined
代码:this.full.Instance.setHeight(500);
this.full.Instance.execCommand('insertHtml', img);
this.full.Instance.execCommand( 'insertimage', { src:success.data['url'], width:'300px', height:'200px' });

图片上传成功之后的路径问题

图片成功上传之后会返回一个路径并且向后台请求图片,进行预览,但是域名是前端的。请问怎么改成后端的域名?

设置内容报错

请问我给编辑器设置内容 为什么会报错. 获取值到没什么问题

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'setContent' of undefined
TypeError: Cannot read property 'setContent' of undefined


setContent(isAppendTo: boolean) {
        let arr = [];
        arr.push("使用editor.setContent('欢迎使用ueditor')方法可以设置编辑器的内容");
        this.full.Instance.setContent('欢迎使用ueditor', isAppendTo);
        alert(arr.join("\n"));
    }

angular5 报错ngDevMode

ERROR in node_modules/@angular/core/src/render3/ng_dev_mode.d.ts(9,11): error TS2451: Cannot redeclare block-scoped variable 'ngDevMode'.
node_modules/ngx-ueditor/node_modules/@angular/core/src/render3/ng_dev_mode.d.ts(9,11): error TS2451: Cannot redeclare block-scoped variable 'ngDevMode'.

UE.getEditor is not a function

clone demo项目,刷新直接如下报错
_UE.getEditor is not a function. (In 'UE.getEditor(this.id, opt)', 'UE.getEditor' is undefined)
我自己的项目也一样,请问怎么解决呀!难道不能刷新吗

只能引入ueditor.all.js吗,可否引入ueditor.all.min.js

我看见
ScriptService.prototype.load = function (path, debug) { var _this = this; if (this.loaded) return this; this.loaded = true; var promises = []; if (!path.endsWith('/')) path += '/'; [path + "ueditor.config.js", debug === true ? path + "ueditor.all.js" : path + "ueditor.all.min.js"].forEach(function (script) { return promises.push(_this.loadScript(script)); }); Promise.all(promises).then(function (res) { _this.emitter.next(true); }); return this; };
debug请问可以配置吗,我想引用ueditor.all.min.js

问题请教:怎么初始化内容

我现在要从后端获取一段文字显示在content中,作为初始化内容。请问我应该怎么做呢?
现在的做法是:在component.ts的

ngOnInit() { this.httpClient.get('/getDocTxt')
.subscribe((docTxt: Map<String, String>) => {
if (docTxt !== null) {
this.txt= docTxt.txt;
}
});}

获取需要初始化显示的内容
然后用
<ueditor (onReady)="setContentData(false)" ...
onReady方法设置内容;但是这样service获取数据有延时,就总是会报错,显示不了初始化数据。

使用1.0.7,升级依赖后,抛异常:Metadata version mismatch for module

开发环境:
windows 10
angular 4,工程采用angular-cli 构建
webstorm.
初始版本:1.0.7
更新版本: 1.0.9

npm start 异常信息:
ERROR in Error: Metadata version mismatch for module ===>/node_modules/ngx-ueditor/index.d.ts
found version 4, expected 3, resolving symbol AppModule ===>/src/app/app.module.ts,

webpack一直加载失败

我使用了webpack来打包,所以看你源码好像动态添加的script是固定的path地址,而不是webpack编译后的JS,所以可能不能兼容webpack,或者只能让我在dist里面放入这个文件,就是:没法打包ueditor。
其实我想问下,为什么我使用

var ue=require('uediotr的js地址')

这样不行呢,这样获取的ue一直是一个空对象。是不是ueditor不支持commonjs,amd,cmd规范导致的。。只能用你那种的动态插入script来注入呢?

无法获取ueditor.config.js和ueditor.all.js文件导致引入失败

npm install后在app.module.ts中import UEditorModule并指定ueditor.js路径目录: path: '/assets/ueditor/':
1512718802 1
将相关文件放置在assets目录下:
1512719013 1
项目运行后报错:
1512718954 1
ueditor.config.js和ueditor.all.js文件已经放置在assets目录下,但是项目运行时却报错无法访问到这两个文件导致加载失败,请问该如何处理?

关于UEditor的图片上传

Hello, 我最近遭遇了截屏并粘贴到UEditor的需求, 而ueditor和后端的强耦合配置让我实在很难受,所以我在ueditor的源码里面做了一些魔改, 新增了一个名为base64pasted的事件来处理这样的逻辑(当然这个命名或者操作手段其实只是一个临时的解决方案).

                //microex:如果为单个本地文件的复制
                if (e.clipboardData.types[0] == "Files" && e.clipboardData.types.length == 1) {
                    var file = e.clipboardData.files[0];
                    //如果文件为图片
                    if (file && ["image/png", "image/jpg", "image/gif"].some(x => x == file.type)) {
                        let fr = new FileReader();
                        fr.onload = () => {
                            me.fireEvent('base64pasted', fr.result, (ossFileName) => {
                                me.body.innerHTML = me.body.innerHTML.concat(`<img data-is-base64="true" src="${ossFileName}"></img>`)
                            });
                        };
                        fr.readAsDataURL(file)
                    }
                    return;
                } else {
                    getClipboardData.call(me, function (div) {
                        filter(div);
                    });
                }

同时在ngx-ueditor中增加了这样的逻辑:

UEditorComponent.prototype.init = function (options) {
        var _this = this;
        if (!window.UE)
            throw new Error('uedito js文件加载失败');
        if (this.instance)
            return;
        // registrer hook
        if (this.defConfig && this.defConfig.hook) {
            if (!this.defConfig._hook_finished) {
                this.defConfig._hook_finished = true;
                this.defConfig.hook(UE);
            }
        }
        this.loading = false;
        this.onPreReady.emit(this);
        this.zone.runOutsideAngular(function () {
            var opt = Object.assign({
                UEDITOR_HOME_URL: _this.path
            }, _this.defConfig && _this.defConfig.options, _this.config, options);
            var ueditor = UE.getEditor(_this.id, opt);
            ueditor.ready(function () {
                _this.zone.run(function () {
                    _this.instance = ueditor;
                    _this.value && _this.instance.setContent(_this.value);
                    _this.onReady.emit(_this);
                });
            });
            ueditor.addListener('contentChange', function () {
                _this.updateValue(ueditor.getContent());
            });
            //!! look here !!
            //!! look here !!
            //!! look here !!
            ueditor.addListener('base64pasted', function (base64) {
                //这里通过绑定的callback去处理base64字符串(比如上传oss)
                _this.onBase64pasted(base64);
            });
        });
    };

虽然问题解决了,但过程当中我觉得以ueditor的方式来定义后端接口其实不是很便捷, 为什么不把图片的粘贴事件直接暴露出来,让我们可以重写,然后自主处理图片的上传逻辑呢?或许我的做法和想法比较简单粗暴,不知道您有没有什么看法呢?

ngx-ueditor与ng5冲突

每次执行npm start 时会产生一下错误导致程序无法启动
/**
*
ERROR in TypeError: staticSymbol.assertNoMembers is not a function
at AotSummaryResolver.resolveSummary (F:\Workspace\WEB - Copy - Copy\src\sentations\web\node_modules@angular\compiler\bundles\compiler.umd.js:31928:2
at CompileMetadataResolver._loadSummary (F:\Workspace\WEB - Copy - Copy\spresentations\web\node_modules@angular\compiler\bundles\compiler.umd.js:14706)
at CompileMetadataResolver.isDirective (F:\Workspace\WEB - Copy - Copy\srresentations\web\node_modules@angular\compiler\bundles\compiler.umd.js:15003)
at CompileMetadataResolver.getTypeDescriptor (F:\Workspace\WEB - Copy - y\src\presentations\web\node_modules@angular\compiler\bundles\compiler.umd.j5269:18)
at F:\Workspace\WEB - Copy - Copy\src\presentations\web\node_modules@angr\compiler\bundles\compiler.umd.js:15131:78
at Array.forEach (native)
at CompileMetadataResolver.getNgModuleMetadata (F:\Workspace\WEB - Copy -py\src\presentations\web\node_modules@angular\compiler\bundles\compiler.umd.15114:49)
at visitLazyRoute (F:\Workspace\WEB - Copy - Copy\src\presentations\web\n_modules@angular\compiler\bundles\compiler.umd.js:29937:104)
at visitLazyRoute (F:\Workspace\WEB - Copy - Copy\src\presentations\web\n_modules@angular\compiler\bundles\compiler.umd.js:29941:17)
at AotCompiler.listLazyRoutes (F:\Workspace\WEB - Copy - Copy\src\presentons\web\node_modules@angular\compiler\bundles\compiler.umd.js:29905:20)
at AngularCompilerProgram.listLazyRoutes (F:\Workspace\WEB - Copy - Copy\presentations\web\node_modules@angular\compiler-cli\src\transformers\progras:157:30)
at Function.NgTools_InternalApi_NG_2.listLazyRoutes (F:\Workspace\WEB - C - Copy\src\presentations\web\node_modules@angular\compiler-cli\src\ngtools
.js:44:36)
at AngularCompilerPlugin._getLazyRoutesFromNgtools (F:\Workspace\WEB - Co- Copy\src\presentations\web\node_modules@ngtools\webpack\src\angular_compilplugin.js:248:66)
at Promise.resolve.then.then (F:\Workspace\WEB - Copy - Copy\src\presentans\web\node_modules@ngtools\webpack\src\angular_compiler_plugin.js:562:50)
at process._tickCallback (internal/process/next_tick.js:109:7)

*/

感觉是和我这个框架的一些插件冲突了

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.