ipyvue icon indicating copy to clipboard operation
ipyvue copied to clipboard

add a find findAll method to widgets ?

Open 12rambau opened this issue 1 year ago • 2 comments

In lot of cases I'm forced to use variable for every single widget that I will modify in the future. It's specifically enoying when the components are for examples V.Html(tag="tr") from a table. I implemented a method to reach child or children of a widget using key, value pair.

def get_children(
        self,
        widget: Optional[v.VuetifyWidget] = None,
        klass: Optional[Type[v.VuetifyWidget]] = None,
        attr: str = "",
        value: str = "",
        id_: str = "",
        elements: Optional[list] = None,
    ) -> List[v.VuetifyWidget]:
        r"""Recursively search for every element matching the specifications.

        multiple parameters can be used to search for matching elements. no error is raised if nothing is found.

        Args:
            widget: the widget to search into
            klass: the vuetify widget class to look for . Leave empty for any.
            attr: the attribute to look at. leave empty for no search
            value: the value of the attr. ignored if attr is not set
            elements: the list used to store found elements

        Returns:
            List containing all matching elements

        Retrieve all children elements that matches with the given id\_.

        Args:
            id\_ (str, optional): attribute id to compare with.

        Returns:
            list with all matching elements if there are more than one, otherwise will return the matching element.

        """
        # id_ was the previous variable it should continue working in this implementation
        # remove kwargs when this will be deprecated
        if id_ != "":
            attr, value = ("id", id_)
            warnings.warn(
                '"id_" is a deprecated argument, use an ("attr", "value") pair instead',
                DeprecationWarning,
            )

        # init the element list
        elements = [] if elements is None else elements

        # init the widget
        widget = self if widget is None else widget

        for w in widget.children:

            # exit if children is not a widget (str, DOM objects.. etc)
            if not isinstance(w, (v.VuetifyWidget, v.Html)):
                continue

            # compare the widget with requirements
            # if no klass is specified, use both vuetifyWidget and Html objects
            is_klass = (
                isinstance(w, klass)
                if klass
                else isinstance(w, ((v.VuetifyWidget, v.Html)))
            )

            # using "niet" as default so that result is True if attr is Falsy
            # "niet" is very unlikely to be used compared to None, False, "none"...
            is_val = w.attributes.get(attr, "niet") == value if attr and value else True

            not (is_klass and is_val) or elements.append(w)

            # always search for nested elements
            elements = self.get_children(w, klass, attr, value, id_, elements)

        return elements

Would you see an interest to implement (and refine) this method in ipyvue ?

12rambau avatar Sep 05 '23 06:09 12rambau

Hi Rambaud,

Yes, this is a very interesting idea. But we have something implemented like this in Reacton:

  • https://github.com/widgetti/reacton/blob/master/reacton/find.py

(example usage in https://github.com/widgetti/reacton/blob/master/reacton/find_test.py)

Although this sits in Reacton, it actually is very widget oriented. However, I'm not sure where this needs to go. I think it is more general than ipyvue right? Almost sounds like it should go into ipywidgets.

Regards,

Maarten

maartenbreddels avatar Sep 17 '23 07:09 maartenbreddels

As I was requested to implemented the class_list management member (https://github.com/widgetti/ipyvue/pull/40) here instead of ipywidgets I assumed that was the correct place for generic method. It would then become available for every widgets generated in ipywidget.

12rambau avatar Sep 17 '23 16:09 12rambau