1

How can I update/change the values of a stored struct instance?

as an example: Let's say I've already deployed a chapter with the content written in a particular color. Later it turns out that I want to use a different color and therefore need to update the array of the already stored struct instance. How can I now modify the color of the existing stored struct instance to contain the new color?

contract NewBook {

    struct ChapterData {
        // string chapterID;
        string title;
        string color;
        uint pages;
    }

    struct BookData {
        // string bookID;
        ChapterData[] chapters;
    }

    mapping(bytes32 => BookData) books; // bookId => BookData

    function addChapter(bytes32 _bookID, string memory title, string color, uint pages) public {
        ChapterData memory c = ChapterData({
            title: title,
            color: color,
            pages: pages
        });
        books[_bookID].chapters.push(c);
    }
1

First you need the reference of the book and then you can get one chapters by passing the index of it (uint256 chapter).

Try with this:

pragma solidity ^0.5.0;

contract NewBook {

    struct ChapterData {
        // string chapterID;
        string title;
        string color;
        uint pages;
    }

    struct BookData {
        // string bookID;
        ChapterData[] chapters;
    }

    mapping(bytes32 => BookData) books; // bookId => BookData

    function addChapter(bytes32 _bookID, string memory title, string memory color, uint pages) public {
        ChapterData memory c = ChapterData({
            title: title,
            color: color,
            pages: pages
        });
        books[_bookID].chapters.push(c);
    }

    function changeColor (bytes32 _bookID, uint256 chapter, string memory color) public {
        ChapterData storage _chapter = (books[_bookID]).chapters[chapter];
        _chapter.color = color;
    }

    function numChapters (bytes32 _bookID) public view returns (uint256) {
        return books[_bookID].chapters.length;
    }

    function getChapterIndex (bytes32 _bookID, string memory title) public view returns (uint256) {
        for (uint i=0; i < books[_bookID].chapters.length; i++) {
            if( keccak256(abi.encodePacked(books[_bookID].chapters[i].title)) == keccak256(abi.encodePacked(title))){
                return i;
            }
        }
    }
}
  • I see, is there an easy way to find the index position? – NowsyMe Jul 13 at 22:32
  • @NowsyMe I don't think so with the current implementation. Maybe you could implement a chapter counter/number per book or something like this. – alberto Jul 13 at 22:44
  • would it make sense to use a mapping to do this? i.e. every time you add a struct to an array, then map the structID of the struct to the length of the array at given time of addition. Then one could have a key-pair overview (bytes 32 => uint) of all the structs and their index position in the array. – NowsyMe Jul 13 at 23:44
  • @NowsyMe It's a possible solution but keep in mind that you will have two different IDs: bookID and chapterID. – alberto Jul 14 at 0:04
  • it makes sense to have two ids when you deal with objectives that should be updateable for me – NowsyMe Jul 14 at 0:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.