Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Angular] How to give a component variable the value of a clicked item #357

Closed
Dako390 opened this issue Nov 25, 2022 · 3 comments
Closed
Labels
👨‍🏫 Help wanted Extra attention is needed ❓ Question Further information is requested

Comments

@Dako390
Copy link

Dako390 commented Nov 25, 2022

Your question and description of the problem goes here
How can give my variable the value of an item I clicked on? I can't use classwide varibales with this. inside of the action function. I want to display an item's properties, e.g. label, color, time, inside of another html element. In my case I want to set the variable selectedTimeslot to the item that has been clicked on.

Code
You can paste your code and data examples here if it will help to answer the question.

// the timeslot the user clicked one; the interface TimeSlot looks like this:
// https://gantt-schedule-timeline-calendar.neuronet.io/documentation/configuration/chart/items
public selectedTimeslot: TimeSlot = {} as TimeSlot;

public clickAction(element: any, data: any) {
    function onClick(event: any) {
      console.log(data.item); 
      console.log(GSTC.api.sourceID(data.item.id));
    }

    element.addEventListener('click', onClick);

    return {
      update(element: any, newData: any) {
        data = newData;
      },

      destroy(element: any, data: any) {
        element.removeEventListener("click", onClick);
      },
    };
  }
  
  // somewhere in the config
  const config = {
  /* ... */
  actions: {
    'chart-timeline-items-row-item': [this.clickAction],
  },
  /* ... */
};

Now I want public selectedTimeslot to be data.item - how can I achieve that?

Thanks a lot in advance!

@Dako390 Dako390 added ❓ Question Further information is requested 👨‍🏫 Help wanted Extra attention is needed labels Nov 25, 2022
@neuronetio
Copy link
Owner

Maybe Selection plugin will do it for you?

https://github.com/neuronetio/gantt-schedule-timeline-calendar/blob/master/examples/complex-1/index.js#L510

selected.mp4

@neuronetio
Copy link
Owner

If for some reason you don't want to use the Selection plugin then I recommend using a template.
Simply take the default template for the item and add your own click event in it.
It will look more or less like this:
(you can also take a look at complex example)

let selectedTimeslot: TimeSlot = {} as TimeSlot;

function myItemClickEvent( ev ){
  const itemElement = ev.target.closest('.gstc__chart-timeline-items-row-item');
  const itemId = itemElement.dataset.gstcid;
  const item = gstc.api.getItem(itemId);
  console.log('Item click from template', item);
  // now you have item id so you can get item data and save it to your global variable
  selectedTimeslot = gstc.state.get('config.chart.items.'+itemId);
}

function chartTimelineItemsRowItemTemplate({
  className,
  labelClassName,
  styleMap,
  cache,
  shouldDetach,
  cutterLeft,
  cutterRight,
  getContent,
  actions,
  slots,
  html,
  vido,
  props,
}) {
  const detach = shouldDetach || !props || !props.item;
  return cache(
    detach
      ? null
      : slots.html(
          "outer",
          html`
            <div
              class=${className}
              data-gstcid=${props.item.id}
              data-actions=${actions()}
              style=${styleMap.directive()}
              @click=${myItemClickEvent}
            >
              ${slots.html(
                "inner",
                html`
                  ${cutterLeft()}
                  <div class=${labelClassName}>${slots.html("content", getContent())}</div>
                  ${cutterRight()}
                `
              )}
            </div>
          `
        )
  );
}

// config
const config = {
  /* ... other settings ... */
  templates: {
    "chart-timeline-items-row-item": chartTimelineItemsRowItemTemplate,
  },
  /* ... other settings ... */
};

@neuronetio
Copy link
Owner

neuronetio commented Nov 25, 2022

PS try not to use the keyword this inside code that is intended for gantt. This often leads to confusion and errors - often less experienced programmers don't quite know how this works inside nested objects.
So try as much as possible to place code from gantt outside of classes.

To solve this problem and the code from the gantt has to be in the class you can use methods inside the class that return the appropriate configuration using the self variable that points to the correct instance e.g.

class MyClass {
  public gstc; // your gstc instance https://github.com/neuronetio/angular-gantt-schedule-timeline-calendar-example/blob/master/src/app/app.component.ts#L98
  public selectedTimeslot = {};

  public getItemClickEvent(){
    const self = this;
    return function myItemClickEvent(ev) {
      const itemElement = ev.target.closest(".gstc__chart-timeline-items-row-item");
      const itemId = itemElement.dataset.gstcid;
      // now you have item id so you can get item data and save it to your variable
      self.selectedTimeslot = self.gstc.api.getItem(itemId);
      console.log("Item click from template", self.selectedTimeslot);
      // or with state
      // self.selectedTimeslot = self.gstc.state.get("config.chart.items." + itemId);
    }
  }

  public getItemTemplate() {
    const self = this;
    const myClickEvent = self.getItemClickEvent(); // we can get things right away to prevent garbarge colletor cleanup
    return function chartTimelineItemsRowItemTemplate({
      className,
      labelClassName,
      styleMap,
      cache,
      shouldDetach,
      cutterLeft,
      cutterRight,
      getContent,
      actions,
      slots,
      html,
      vido,
      props,
    }) {
      const detach = shouldDetach || !props || !props.item;
      return cache(
        detach
          ? null
          : slots.html(
              "outer",
              html`
                <div
                  class=${className}
                  data-gstcid=${props.item.id}
                  data-actions=${actions()}
                  style=${styleMap.directive()}
                  @click=${myClickEvent} // or self.getItemClickEvent()
                >
                  ${slots.html(
                    "inner",
                    html`
                      ${cutterLeft()}
                      <div class=${labelClassName}>${slots.html("content", getContent())}</div>
                      ${cutterRight()}
                    `
                  )}
                </div>
              `
            )
      );
    };
  }

  public getGSTCConfig() {
    const self = this;
    // config
    const config = {
      /* ... other settings ... */
      templates: {
        "chart-timeline-items-row-item": self.getItemTemplate(),
      },
      /* ... other settings ... */
    };
    return config;
  }
}

💡 We do similar things in angular example

@neuronetio neuronetio pinned this issue Nov 25, 2022
@neuronetio neuronetio changed the title How to give a component variable the value of a clicked item in Angular [Angular] How to give a component variable the value of a clicked item Nov 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
👨‍🏫 Help wanted Extra attention is needed ❓ Question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants