GithubHelp home page GithubHelp logo

Comments (8)

nathanieltagg avatar nathanieltagg commented on May 3, 2024 4

Here's a working example for a custom component I've been working on. You just need this single file, then add the component to the Builder custom menu to get at it.


///
/// Custom component a number with a range of nominal values that shows a warning if out of
/// specification, but does not throw a form error.
///

var NumberComponent = Formio.Components.components.number;
class SpecNumberComponent extends NumberComponent{

  static schema(...extend) {
    return super.schema({
      // "specification_nominal":0,
      // "specification_tolerance":1e99,
      // "specification_minimum": -1e99,
      // "specification_maximum": 1e99,
      "label": "SpecNumberComponent",
      "key": "specvalue",
      "type": "SpecNumberComponent",
      "input": true  
    }, ...extend);
  }

  static get builderInfo() {
    return {
      title: 'Number with tolerance',
      group: 'custom',
      icon: 'arrows-h',
      weight: 72,
      documentation: '#', 
      schema: this.schema()
     };
  }

  showNominal()
  {
    var nominal = "";
    if('specification_nominal' in this.component)  
      nominal = "Nominal "+ this.component.specification_nominal;
    if(('specification_nominal' in this.component) && ('specification_tolerance' in this.component)) {
      nominal += "±"+this.component.specification_tolerance;
    }
    if('specification_minimum' in this.component) nominal += " min "+this.component.specification_minimum;
    if('specification_maximum' in this.component) nominal += " max "+this.component.specification_maximum;
    if(this.component.units) nominal += " " + this.component.units;
    this.specification_label.html(nominal).removeClass('warning');
  }

  checkValue(val)
  {
    this.showNominal();

    if(val === null) return;
    var warning = null;
    if(('specification_nominal' in this.component) && ('specification_tolerance' in this.component)) {
      if((val - this.component.specification_nominal) > this.component.specification_tolerance) 
        warning = "Above tolerance." ;

      if((val - this.component.specification_nominal) < -this.component.specification_tolerance) {
          warning = "Below tolerance.";
        }
    }

    if('specification_minimum' in this.component) {
      if(val < this.component.specification_minimum)
        warning = "Below minimum specification. ";
    }

    if('specification_maximum' in this.component) {
      if (val > this.component.specification_maximum)
        warning = "Above maximum specification. ";
    }
    if(warning) this.specification_label.prepend("<span class='specification-warning'>"+warning+"</span>");
  }


  renderElement(value,index) 
  {
    var tpl = '';
    tpl += super.renderElement(value,index);
    tpl += "<div class='specification-label'></div>";

    return tpl;
  }

  attach(element) 
  {
    /// Called after rendering, just as the component is being inserted into the DOM.
    /// .. just like a text area...
    super.attach(element);
    this.specification_label = $(".specification-label",this.element);
    this.showNominal();
  }


  setValueAt(index,value,flags)
  {
    this.checkValue(value);
    return super.setValueAt(index,value,flags);
  }

  getValueAt(index)
  {
    var value = super.getValueAt(index);
    this.checkValue(value);
    return value;
  }







}


SpecNumberComponent.editForm = function(a,b,c)
{
    var form = NumberComponent.editForm(a,b,c);
    var tabs = form.components.find(obj => { return obj.type === "tabs" });
    var datatab = tabs.components.find(obj => {return obj.key=='data'});

    // Remove 'multiple components'. I could probably make it work.. but nah
    datatab.components.splice(datatab.components.findIndex(obj=>{return obj.key = "multiple"}),1);
    var displaytab = tabs.components.find(obj => {return obj.key=='display'});


    datatab.components.splice(1,0,
      {
        "input": true,
        "key": "specification_nominal",
        "label": "Nominal Value",
        "placeholder": "Nominal value ",
        "tooltip": "This is the nominal value this element should hold",
        "type": "number",
      },
      {
        "input": true,
        "key": "specification_tolerance",
        "label": "Tolerance",
        "tooltip": "This is the tolerance, plus or minus, around the main value. If outside this range, a warning will show.",
        "type": "number",
      },
      {
        "input": true,
        "key": "specification_minimum",
        "label": "Minimum Specification",
        "tooltip": "If less than this value, a warning will show.",
        "type": "number",
      },      
      {
        "input": true,
        "key": "specification_maximum",
        "label": "Maximum Specification",
        "tooltip": "If greater than than this value, a warning will show.",
        "type": "number",
      },
      {
        "input": true,
        "key": "units",
        "label": "Units",
        "tooltip": "Optional units to show",
        "type": "textfield",
      }
  );


    return form;
}


Formio.Components.addComponent('SpecNumberComponent', SpecNumberComponent);


from contrib.

0liver avatar 0liver commented on May 3, 2024 2

While your answer is over 2 years old now, @travist, the repo hasn't changed for over 3 years.

I feel that to really build a community around formiojs, a clear and straight-forward on-boarding experience is mandatory. Scanning open issues for valuable hints buried in comments is not something that should be expected before getting started.

As you've stated:

[...] this is our recommended way of creating Custom components since it provides customers a template to be able to have their own library of custom components [...]

So, please, make the necessary changes - as small as they may be - and add a "Getting started" paragraph in your Readme that covers not the usage but the development of this module.

Thank you.

from contrib.

travist avatar travist commented on May 3, 2024 1

The "npm install" probably fails because we need to include the formiojs library as a "devDependency" as well as a "peerDependency" so that the build can still be completed. That is an easy change to make and should not block using the contrib library as a model to create custom components. Moving forward, this is our recommended way of creating Custom components since it provides customers a template to be able to have their own library of custom components and also includes a way of compiling them so that they work with all browsers (using webpack + typescript).

from contrib.

adventmedia avatar adventmedia commented on May 3, 2024

remove the "prepublish": "npm run build" line from package.json and npm install runs without errors.
Of course that only defers the real problem - the script specified in the "prepublish" step:
"build": "tsc && gulp templates && npm run webpack && node-sass ./src/sass/contrib.scss ./dist/formio-contrib.css"
This fails. To fail spectacularly, just run tscby itself.
If we're not to use npm run build to build, then what?

from contrib.

adventmedia avatar adventmedia commented on May 3, 2024

It also seems odd that package.json does not include 'formiojs' which is imported in /src/components/CheckMatrix/CheckMatrix.ts.

from contrib.

travist avatar travist commented on May 3, 2024

formiojs is a peerDependency and that is intended. The reason for this is we want the users who are including this library to already have formiojs installed as a dependency and we should be using that instance of that library instead of the one included from this library. This actually resolves a pretty significant issue where the components would get registered on the wrong formiojs instance.

from contrib.

adventmedia avatar adventmedia commented on May 3, 2024

so it seems I'm barking up the wrong tree - I'm trying to understand how to create a custom component based on this example.

from contrib.

daneformio avatar daneformio commented on May 3, 2024

Closing this thread as it is outdated. Please re-open if it is still relevant. Thank you for your contribution!

from contrib.

Related Issues (14)

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.